Is it possible, while creating an instance of an object, to check during the instantiation itself the type of the parameter passed to the constructor, and set one of the object's variable accordingly?
This is what I'm trying to do:
function Test(num1) {
this.num1 = num1;
this.isValidNumber = (function() {
console.log(this.num1); // logs "undefined" upon instantiation
if (isNaN(this.num1)) {
return false;
} else {
return true;
}
}());
}
var testObj = new Test(5);
I want isValidNumber's value to be true or false according to the parameter passed to the constructor.
Your IIFE (Immediately-Invoked Function Expression) creates a new context, which means this doesn't point to your constructor anymore but to the Window object (unless you're using strict mode which would make it undefined). One possible solution is to execute this function with the right context:
this.isValidNumber = function() {
if (isNaN(this.num1)) {
return false;
} else {
return true;
}
}.call(this);
The much simpler solution is obviously:
function Test(num1) {
this.num1 = num1;
this.isValidNumber = !isNaN(this.num1);
}
First of all, the code could (and probably should) be rewritten the following way:
function Test(num1) {
this.num1 = num1;
console.log(this.num1);
this.isValidNumber = !isNaN(this.num1);
}
As for the reason why your code is not working as expected – your self invoking function has its own this parameter which is unrelated to the this parameter within your constructor.
In this case the this parameter of your self invoking function references the global object. (In strict mode it would've been undefined)
If you really need to reference the this parameter of a containing function then there are several ways to achieve this, the simplest of which being:
function Test(num1) {
this.num1 = num1;
var self = this;
this.isValidNumber = (function() {
console.log(self.num1);
return !isNaN(self.num1));
}());
}
In your particular case you don't even need to capture it, and this would also achieve the same effect:
function Test(num1) {
this.num1 = num1;
this.isValidNumber = (function() {
console.log(num1);
return !isNaN(num1));
}());
}
But again, the self invoking function is simply not required here.
This in the inner function no longer references the parent object. A common way of storing the object reference is to create a 'self' variable and assign this to it when it's in the correct scope
function Test(num1) {
var self = this;
this.num1 = num1;
this.isValidNumber = (function() {
console.log(self.num1);
if (isNaN(self.num1)) {
return false;
} else {
return true;
}
}());
}
var testObj = new Test(5);
Related
I have read this answer and IIFE but I can't seem to find the correct solution to my problem.
I have a simple class here:
define(['jquery'], function($) {
// Need 'self' because someCallback() is being called with .call() and 'this' changes
var self;
function Foo(number) {
self = this;
this.someNumber = number;
}
Foo.prototype = {
someCallback: function () {
//Use self because 'this' changes to a DOM element
var num = self.someNumber;
//Do something with the num
return num * 2;
}
};
return Foo;
});
and someCallBack() is being called by a jQuery plugin using .call(). Because of this, the context changed, hence the use of the self variable.
However, this is wrong because:
define(['foo'], function(Foo) {
describe('context question', function () {
var foo1 = new Foo(1);
var foo2 = new Foo(2);
it('"this" should work', function () {
var call1 = foo1.someCallback.call(this); // 4
var call2 = foo2.someCallback.call(this); // 4
expect(call2).toBe(4); // Only works because it is 'new' last
expect(call1).toBe(2); // Fails because 'self' is taken from foo2
});
});
});
How exactly should I wrap the self variable to make this code work?
You could probably just use the revealing module pattern and declare it as a "global" variable (local to the module):
define(['jquery'], function($) {
var someNumber;
function Foo(number) {
someNumber = number;
}
Foo.prototype = {
someCallback: function () {
return someNumber * 2;
}
};
return Foo;
});
Two ways of calling an object method which stores its own this value include
Define the method as a nested function which references its this value in a closure which stores this value in a variable. The function defined could be anonymous or declared with a name but must be evaluated each time a class instance is created, so as to create a new Function object capturing different values of self in function scope.
Take a statically defined function object and bind its this value using bind. Bind creates a new wrapper function object each time it is called.
The first method looks like (without Jquery or Jasmine):
function Foo(number)
{ var self = this;
this.num = number;
this.someCallback = function() // method with new Foo object stored as self in function scope
{ // something with num:
return self.num * 2;
}
}
and the second method could look like
function Foo(number)
{ this.num = number
this.someCallback = this.someCallback.bind(this); // bind prototypical method as local method.
}
Foo.prototype = {
someCallback: function () {
// this value is bound by constructor;
//Do something with the num
return this.num * 2;
}
};
I have this code - I just wonder why after I add 'var' to foo variable, it doesn't work (it shows me foo is undefined)... Can anyone help explain these two functions? Thanks!
window.onload = function() {
var test = foo().steps(2);
console.log(test);
}
(function() {
//if I remove var, then it prints out a function which is what I expected
var foo = function() {
var steps = 1;
function callMe(g) {
//do something else
console.log("hello" + g);
}
callMe.steps = function(x) {
//if no arguments then return the default value
if (!arguments.length) return steps;
console.log(arguments);
//otherwise assign the new value and attached the value to callMe
steps = x;
return callMe;
}
return callMe;
}
})();
adding var to foo makes foo a local variable inside the IIFE and thus you can't access it outside.
I want to be able to assign a property to a function inside the function itself. I do not want to assign it to the object of invocation. So I want the equivalent of doing this:
var test = function() {
return true;
};
test.a = 'property on a function';
alert(test.a);
Instead of this, where the property is assigned to a global object:
var testAgain = function() {
this.a = "this property won't be assigned to the function";
return true;
};
testAgain();
alert(window.a);
Edit: To clarify, I'm wondering if there's something like this:
var test = function() {
function.a = 'property on a function';
};
alert(test.a); // returns 'property on a function'
Without knowing that the function is called test or having to execute it.
I know of course this isn't valid syntax
[is there a way to set a property on a function] without knowing that the function is called test or having to execute it.
Emphasis mine.
You can set a property on a function without knowing what its global variable name is necessarily going to be, however you do have to have a reference to the function in one way or another.
The module pattern is as close of a fit as I can think of:
window.test = (function () {
//the function could be named anything...
function testFn() {
...code here...
}
//...so long as the same name is used here
testFn.foo = 'bar';
return testFn;
}());
window.test.foo; //'bar'
The outer closure prevents testFn from being accessed anywhere globally, so all other references will have to use window.test.
This part of the answer is associated with the prior version of the question.
The simplest way of doing this is to use a named function:
var test = function testFn() {
testFn.foo = 'bar';
return true;
};
test.foo; //undefined
test();
test.foo; //'bar'
A better way of doing this is to use the module pattern so that you don't accidentally create issues with global leakage:
var test = (function () {
function ret() {
ret.foo = 'bar';
return true;
}
return ret;
}());
test.foo; //undefined
test();
test.foo; //'bar'
var testAgain = function() {
arguments.callee.a = "this property won't be assigned to the function";
return true;
};
testAgain();
alert(testAgain.a);
You can do this by simple using the name to assign the property like this:
var test = function () {
test.a = 'a';
return true;
};
When test is invoked, the property will be set.
Demo
You could use arguments.callee, as su- said, but that's considered really bad practice. Also, it won't work in strict mode.
var test = function() {
test.a = 'a';
};
Or you can use prototypes, read more here.
I want to build a javascript function that maintains state. Here's a pattern that I've come up with, but something in the back of my mind tells me this is an anti-pattern.
function f() {
var state = 1;
f = function() {
return state++;
};
return f();
};
Is there anything wrong with this? If so, what's a better approach?
Well it's a matter of opinion what the best way is, but (although I know it works) I'm a little uncomfortable with having the function overwrite itself. A similar pattern that doesn't do that but still uses practically the same closure idea is this:
var f = function() {
var state = 1;
return function() {
return state++;
};
}();
Or here is another way:
function f() {
return f.state++;
}
f.state = 1;
Of course with the f.state method the advantage and disadvantage (depending on your needs) is that the .state property can be read and modified by other code.
Normally, you set a closure scope and return a function that has access to that scope. Every time that function is now called, the state will remain as long as that function exists. Example:
var statefulFunction = function() {
// set up closure scope
var state = 1;
// return function with access to the closure scope
return function() {
return state++;
};
}(); // immediately execute to return function with access to closure scope
var first = statefulFunction(); // first === 1
var second = statefulFunction(); // second === 2
Another pattern is to create a closure scope and return an object with methods that have access to that closure scope. Example:
var myStatefulObj = function() {
// set up closure scope
var state = 1;
// return object with methods to manipulate closure scope
return {
incr: function() {
state++;
},
decr: function() {
state--;
},
get: function() {
return state;
}
};
}();
myStatefulObj.incr();
var currState = myStatefulObj.get(); // currState === 2
myStatefulObj.decr();
currState = myStatefulObj.get(); // currState === 1
A better way to achieve this might be to use an Immediately-Invoked Function Expression (IIFE) to encapsulate your state.
var f = (function () {
var state = 1;
return function() {
return state++;
};
}());
console.log(f()); // 1
console.log(f()); // 2
Are the JavaScript code snippets given below some sort of function declaration? If not can someone please give an overview of what they are?
some_func = function(value) {
// some code here
}
and
show:function(value){
// some code here
}
There are six ways/contexts in which to create functions:
1) Standard declarative notation (most familiar to people with C background)
function foo() {}
All the rest are function expressions:
2) As a method of an object literal
var obj = {
foo: function() {}
};
3) As a method of an instantiated object (created each time new is exectued)
var Obj = function() {
this.foo = function() {};
};
4) As a method of a prototype (created only once, regardless of how many times new is executed)
var Obj = function() {};
Obj.prototype.foo = function() {};
5) As an anonymous function with a reference (same effect as #1) *
var foo = function() {};
6) As an immediately executed anonymous function (completely anonymous)
(function() {})();
* When I look at this statement, I consider the result. As such, I don't really consider these as anonymous, because a reference is immediately created to the function and is therefore no longer anonymous. But it's all the same to most people.
The first one is simply creating an anonymous function and assigning it to a variable some_func. So using some_func() will call the function.
The second one should be part of an object notation
var obj = {
show:function(value){
// some code here
}
};
So, obj.show() will call the function
In both cases, you are creating an anonymous function. But in the first case, you are simply assigning it to a variable. Whereas in the second case you are assigning it as a member of an object (possibly among many others).
First is local (or global) variable with assigned anonymous function.
var some_name = function(val) {};
some_name(42);
Second is property of some object (or function with label in front of it) with assigned anonymous function.
var obj = {
show: function(val) {},
// ...
};
obj.show(42);
Functions are first-class citizens in JavaScript, so you could assign them to variables and call those functions from variable.
You can even declare function with other name than variable which that function will be assigned to. It is handy when you want to define recursive methods, for example instead of this:
var obj = {
show: function(val) {
if (val > 0) { this.show(val-1); }
print(val);
}
};
you could write:
var obj = {
show: function f(val) {
if (val > 0) { f(val-1); }
print(val);
}
};
One way of doing it:
var some_func = function(value) {
// some code here
}
Another way:
function some_funct() {
}
Yet another way:
var some_object={};
some_object["some_func"] = function() {};
or:
var some_object={};
some_object.some_func = function() {};
In other words, they are many ways to declare a function in JS.
Your second example is not correct.
The first one is a function declaration assigned to a variable (at least it should be, despite the fact that it's missing the variable type declaration first), the second one is probably related to a object declaration.
They are called anonymous functions; you can read more about them here:
http://www.ejball.com/EdAtWork/2005/03/28/JavaScriptAnonymousFunctions.aspx
The first example creates a global variable (if a local variable of that name doesn't already exist) called some_func, and assigns a function to it, so that some_func() may be invoked.
The second example is a function declaration inside an object. it assigns a function as the value of the show property of an object:
var myObj = {
propString: "abc",
propFunction: function() { alert('test'); }
};
myObj.propFunction();
The first one...
some_func = function(value) {
// some code here
}
is declaring a variable and assigned an anonymous function to it, which is equivalent to...
function some_func (value) {
// some code here
}
The second one should look like this...
obj = {
show:function(value){
// some code here
}
}
// obj.show(value)
and equivalent to...
//pseudo code
class MyClass {
function show (value) {
// some code here
}
}
obj = new MyClass(); // obj.show(value)
Cheers