0

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?

asked Jun 18, 2013 at 10:50
8
  • i have no problem with answering your own question but why have you written 'I don't understand' in the question Commented Jun 18, 2013 at 10:53
  • 3
    He's learning quickly...? Commented Jun 18, 2013 at 10:54
  • Yeah, I figured it out just after I finished the question. Commented 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. Commented Jun 18, 2013 at 11:00
  • 1
    Yes, 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. Commented Jun 18, 2013 at 11:19

4 Answers 4

2

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

answered Jun 18, 2013 at 11:24
Sign up to request clarification or add additional context in comments.

1 Comment

Great answer and fantastic example to go with. Cheers!
2

Because objects are passed by reference, whereas an undefined variable is not.

answered Jun 18, 2013 at 10:50

3 Comments

No. undefined is also a object reference. You are just overwriting the reference with a different one.
Actually objects are passed to a function as a copy of the reference, that's a big difference.
@Quentin 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.
2

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
answered Jun 18, 2013 at 11:25

2 Comments

There are no closures in the examples since the object in question is passed as an argument to the function and I thiknk you mean "assign an object to the variable" and not "defined the variable as an object " since you can't define a variable as an object.
Yes, I was in the process of editing and was interrupted by someone when you commented.
0

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.

answered Jun 18, 2013 at 11:40

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.