Geeks,
I have the following codes:
Snippet A:
var x = (function(){ this.id="Dog"; return this; }());
var y = (function(){ this.id="Cat"; return this; }());
alert(x.id); //outputs Cat
alert(y.id); //outputs Cat
Snippet B:
var x = (new function(){ this.id="Dog"; });
var y = (new function(){ this.id="Cat"; });
alert(x.id); //ouputs Dog
alert(y.id); //outputs Cat
Why is x replaced by y in Snippet A and not on B?
The difference between the two is that Snippet B is using a constructor function by prefixing the call with the new keyword, while snippet A is not. This is the short answer.
The long answer is that although snippet A introduces a new scope on each anonymous function invocation, since it is not being used in a constructor context it's this variable simply points to the global window object. So snippet A is equivalent to this:
var x = (function(){ window.id="Dog"; return window; }());
var y = (function(){ window.id="Cat"; return window; }());
Thus, each invocation just clobbers the same [global] variable.
Since snippet B is using the new keyword, you define and immediately call a constructor function. JavaScript proceeds to initialize the this variable inside the constructor function to point to a new instance of the [just defined] anonymous function.
You may have seen the new function(){} idiom some time ago being touted as the best way to define and immediately execute a block of code. Well, it comes with the overhead of JavaScript object instantiation (as you've found), and is not generally used as widely anymore.
In the snippet A, on x and y, the this keyword refers to the global object, you are creating setting the value to the same global variable (window.id).
In the snippet B, you are using the new operator, and the functions are executed as constructor functions, the this keyword refers to a newly created object.
To avoid that behavior in your snippet A, you can create a new object instance and use it instead of this:
var x = (function(){
var instance = {};
instance.id = "Dog";
return instance;
}());
var y = (function(){
var instance = {};
instance.id = "Cat";
return instance;
}());
alert(x.id); //outputs Dog
alert(y.id); //outputs Cat
When you call global functions, since they are members of the global object:
globalFunction();
Is equivalent to:
window.globalFunction();
And the context inside that function will be the global object itself (window).
Related
Is there a way to get the Function object, while the function is executing?
I am assigning properties to my function, and want to access them. "this" doesn't help. Something like:
a.b=function(){...code...};
a.b.c=100;
I want to access a.b.c from the code in the function, without knowing its own name. "this" refers to a. How can get b?
I tried binding the function to his own object, but I couldn't.
Thank you.
I'm adding this example, I have to repeat after several different "theString" and "someSpecificValues":
Object.defineProperty(theObject, theString, {get: function(...){...}.bind(theObject, someSpecificValues), configurable: true});
You can use a named function expression for this:
var a = {};
a.b = function myFunc() {
console.log(myFunc.c);
};
a.b.c = 100;
a.b();
It allows code inside the function to access the function itself, but does not add the identifier to the enclosing scope.
Edit: Here is a more elaborate example of how the name myFunc only exists within the function:
var a = {};
a.b = function myFunc() {
console.log(myFunc.c);
};
a.b.c = 100;
a.d = function myFunc() {
console.log(myFunc.c);
};
a.d.c = 300;
a.b(); // logs 100
a.d(); // logs 300
console.log(typeof myFunc); // logs "undefined"
// create a myFunc variable
var myFunc = function() {
console.log("nooooooo!!!!");
};
a.b(); // STILL logs 100. the myFunc variable in this scope
// has no effect on the myFunc name that a.b uses
function callFunc(theFunc) {
theFunc();
}
callFunc(a.d); // STILL logs 300
// ===========================
function returnNamedFunction () {
return function myFunc() {
console.log(myFunc.c);
};
}
var iGotAFunction = returnNamedFunction();
iGotAFunction.c = 700;
iGotAFunction(); // logs 700
In the case when you cannot use a named function expression, e.g. when you are using .bind() on it, then an IIFE will suffice most of the time:
var myObj = {};
myObj.theFunc = (function () {
var f = function (arg1, arg2) {
console.log(this.theProp);
console.log(arg1);
console.log(arg2);
console.log(f.lista);
}.bind(myObj, "A!");
return f;
})();
myObj.theProp = "B!";
myObj.theFunc.lista = [1, 2, 3];
myObj.theFunc("C!");
There are two ways to get current function.
One is "almost deprecated" usage of arguments.callee. In function body it always refers to this function.
var a = {};
a.b = function () {
console.log(arguments.callee.c);
};
a.b.c = 100;
a.b();
arguments.callee is forbidden in strict mode. Reference.
The second one is using named function expression as JLRishe pointed.
arguments.callee pros and cons
Advantages:
it can be safely used with bound functions (arguments.callee refers to bound function)
it can be used with functions created using new Function
Disadvantages:
it can slow your program due to disabling certain optimisations
it's considered as almost deprecated
it can't be used in strict mode
Named function expression pros and cons
Advantages:
it's faster than arguments.callee
it's easier to understand how it works
Disadvantages:
it won't work as expected with bound functions (functionName will refer to original function, not bound one)
it can't be used in functions created with new Function
I've been wondering what is the difference between:
function getBasicRow() {}
getBasicRow : function() {}
I've seen the 2nd function used by vtiger CRM and hifive (http://www.htmlhifive.com/)
The second one assigns the function to a property on some object literal, so the scope of the function is determined by the property.
The first one creates a named function without assigning it to a variable. The function will be hoisted to the closest function scope.
An elobrative explanation that I found here and would like to share it.
The different ways in which a function can be defined in javascript are:
function A(){}; // function declaration
var B = function(){}; // function expression
var C = (function(){}); // function expression with grouping operators
var D = function foo(){}; // named function expression
var E = (function(){ // immediately-invoked function expression (IIFE) that returns a function
return function(){}
})();
var F = new Function(); // Function constructor
var G = new function(){}; // special case: object constructor
What exactly is hoisting?
The interesting thing about these is that they are “hoisted” to the top of their scope, which means this code:
A();
function A(){
console.log('foo');
};
Gets executed as this code:
function A(){
console.log('foo');
};
A();
Which practically means that, yes, you can call the functions before they’re written in your code. It won’t matter, because the entire function gets hoisted to the top of its containing scope.
Variable declaration hoisting
Variable declarations are hoisted to the top of their scope, somewhat similarly to function hoisting except the contents of the variable are not hoisted as well. This happens with all variables, and it means it’s now happening with our functions, now that we’re assigning them to variables.
This code:
var A = function(){};
var B = function(){};
var C = function(){};
Will be executed as this:
var A, B, C; // variable declarations are hoisted
A = function(){};
B = function(){};
C = function(){};
Therefore the order of setting and calling this type of function is important:
// this works
var B = function(){};
B();
// this doesn't work
B2(); // TypeError (B2 is undefined)
var B2 = function(){};
The second example gives us an error because only the variable B2’s declaration is hoisted, but not its definition, thus the “undefined” error.
Courtesy: DavidBCalhoun
What does this point to in this fiddle?
This copies the core parts of jQuery into a simple fiddle.
How can I test for what this points to?
http://jsfiddle.net/tFhFD/3/
Reference
http://code.jquery.com/jquery-latest.js
Read this introduction into the this keyword. You don't really know what this points to, it depends on the invocation of the function.
However, as the init function is invoked with the new keyword, this will be a new object that inherits from the init.prototype object - an instance of the init constructor function.
To inspect the value of this, use your debugger. You can also console.log(this).
var $A = function (test) {
return new $A.prototype.init(test);
};
$A.prototype = {
init: function (test) {
var a = 'function_var';
this[0] = a;
this[1] = arguments[0];
}
};
document.getElementById('foo').innerHTML = $A('hi_there')[0];
console.debug(jQuery('hi_there'));
this in "this" case points to the instance of the init function.
Calling $A's constructor function returns a new instance of $A's prototype init function.
regardless of the wisdom of such a naming scheme, is the following valid?
var F = function() {
this.f1 = function() {}
}
F.f1 = function() {}
// "static" call
var v1 = F.f1();
// prototype call
var f = new F();
var v2 = f.f1();
it seems it should be ok since, for example, var and this variables within an object function do not share the same space.
Yes, that is valid.
In your example, F is a function which you assign a property called f1 which is a function itself. If you were to change the code to read f = new F(), then f is an object which inherits from F's prototype, but they're still two distinct objects.
It is valid.
Like the others have stated, there are no prototype related issues here.
You are attaching 2 propertyes to 2 different objects:
the so called "static" function is attached to the function definition (F)
the so called "public" function is attached to the object returned by the constructor (new F())
So, since F !== new F(), they are 2 different thing with different props.
If you want to make use of the prototypal inheritance, you can consider the following example:
var F = function(){}
// function visible to all of F's instances
F.prototype.f1 = function(){console.log("I'm inherited!");}
// a so called "static" function
F.f1 = function(){console.log("I'm static!");}
var instance1 = new F();
var instance2 = new F();
// function visible only to this instance of F
instance1.f1 = function(){console.log("I'm visible only to this instance of F");}
So when I declare a variable outside the scope of any function, it becomes a property of the window object. But what about when I declare a variable inside the scope of a function? For example, in the following code I can treat x as a property of window, i.e., window.x, but what about y? Is it ever the property of an object?
var x = "asdf1";
function test() {
var y = "asdf2";
}
test();
It becomes a property of the Variable object associated with the function call. In practice, this is the same thing as the function call's Activation object.
I don't believe that the Variable object is accessible to running JavaScript code, though; it's more of an implementation detail than something you can take advantage of.
Access all local variables is a related question here on SO.
In order to declare a JS variable a property of an object you need to either use the new Object(); method or the {} syntax.
var variableName = new Object();
var variableName = {myFirstProperty:1,myNextProperty:'hi',etc};
Then you can assign child objects or properties to said variable object
variableName.aPropertyNameIMadeUp = 'hello';
variableName.aChildObjectNameIMadeUp = new Object();
As such the new variable object is associated with a method if it is within the method call.
Cheers
See following example (I have copy from other question-answer) very nice:
// a globally-scoped variable
var a=1;
// global scope
function one(){
alert(a);
}
// local scope
function two(a){
alert(a);
}
// local scope again
function three(){
var a = 3;
alert(a);
}
// Intermediate: no such thing as block scope in javascript
function four(){
if(true){
var a=4;
}
alert(a); // alerts '4', not the global value of '1'
}
// Intermediate: object properties
function Five(){
this.a = 5;
}
// Advanced: closure
var six = function(){
var foo = 6;
return function(){
// javascript "closure" means I have access to foo in here,
// because it is defined in the function in which I was defined.
alert(foo);
}
}()
// Advanced: prototype-based scope resolution
function Seven(){
this.a = 7;
}
// [object].prototype.property loses to [object].property in the scope chain
Seven.prototype.a = -1; // won't get reached, because 'a' is set in the constructor above.
Seven.prototype.b = 8; // Will get reached, even though 'b' is NOT set in the constructor.
// These will print 1-8
one();
two(2);
three();
four();
alert(new Five().a);
six();
alert(new Seven().a);
alert(new Seven().b);