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?
-
i have no problem with answering your own question but why have you written 'I don't understand' in the questionbugwheels94– bugwheels942013年06月18日 10:53:45 +00:00Commented Jun 18, 2013 at 10:53
-
3He's learning quickly...?Teemu– Teemu2013年06月18日 10:54:19 +00:00Commented Jun 18, 2013 at 10:54
-
Yeah, I figured it out just after I finished the question.Dan Prince– Dan Prince2013年06月18日 10:54:49 +00:00Commented Jun 18, 2013 at 10:54
-
Would the downvoters give me something to go on? Just a comment on how I could improve this question would be great.Dan Prince– Dan Prince2013年06月18日 11:00:33 +00:00Commented Jun 18, 2013 at 11:00
-
1Yes, we are. Oddly, when I created a fiddle, it performs as you describe, but when I run it in Firebug's console...ah, never mind, I just see the copy-paste mistake I made.Derek Henderson– Derek Henderson2013年06月18日 11:19:02 +00:00Commented Jun 18, 2013 at 11:19
4 Answers 4
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
1 Comment
Because objects are passed by reference, whereas an undefined variable is not.
3 Comments
undefined is also a object reference. You are just overwriting the reference with a different one.undefined is not an object reference, it's a primitive value type. Well.. you could say it's an un-resolvable reference (IsUnresolvableReference - true), but that sounds very counter intuitive to me. Dan - Everything is passed by value, when you pass a reference you pass its value around. That's why var a={a:3};(function(x){ x={b:5})(a);a; will return {a:3} for example.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
2 Comments
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.