Reputation: 29989
I have been experimenting with ways to attach methods and variables to an object with self-invoking anonymous functions and come across some behavior that I don't understand.
I define the variable before the function and pass it in as an argument, methods are attached to the reference, but outside, name
remains undefined.
var name;
(function(exports) {
exports = {};
exports.method = function() {
// do stuff
};
})(name);
alert(name === undefined); // true
But when the variable is initialized outside of the function, rather than inside the correct properties are attached as I would expect.
var name2 = {};
(function(exports) {
exports.method = function() {
// do stuff
};
})(name2);
alert(name2 === undefined); // false
alert(name2.method); // method is defined
Why?
Upvotes: 0
Views: 94
Reputation: 9706
In the first example, you overwrite the copy of your object with a new object and then assign it a method. That object and method will not be available outside the function.
In the second example, you defined the variable as an object outside of the function and did not overwrite the reference with a new object. Therefore, the method is attached to the object that is passed in.
If you were to create a third example where you define the variable outside the function and then overwrite the reference to it inside of the function --
var name3 = {};
(function(exports) {
exports = {};
exports.method = function () {
// do stuff
};
})(name);
-- you would find that the method is once again undefined.
console.log(name === undefined); // false
console.log(name.method); // undefined
Upvotes: 2
Reputation: 4185
In the first example "name" and "exports" share a pointer to undefined until you specify that "exports" points to an empty object, but "name" is still pointing to undefined.
In the second example "name" and "exports" share a pointer to an object. Later the object is modified to have a new property, but the pointers are still the same for both vars.
Upvotes: 0
Reputation: 21742
The trick of passing an object from outside the function scope as a parameter to a self executing function is a handy one when it comes to closures and what works with closures is that the reference to the external object (in your first example the reference stored in name
) is passed by copy (that is a copy of the reference).
Any changes to the object through the copy of the reference will have effect outside the function E.g. in your second example
exports.method = function() {
// do stuff
};
adds a method to the object identified by name2. However if you override the reference that the parameter holds as you do in
exports = {}
Then you are simply storing a new reference in the same variable that used to hold the (copy of) original reference
The copying trick is needed at times such as when using closures and iteration variables e.g.
var i;
for(i=0,;i<10;i++){
setTimeout(function(){console.log(i)},3000);
}
will print 9
ten times
whereas
var i;
for(i=0,;i<10;i++){
setTimeout((function(i){return function(){console.log(i)};})(i),3000);
}
will print 0,1,2,3,4,5,6,7,8,9
Upvotes: 2
Reputation: 29989
Because objects are passed by reference, whereas an undefined variable is not.
Upvotes: 3