By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,958 Members | 1,384 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,958 IT Pros & Developers. It's quick & easy.

Please explains why this happens w/ anon functions

P: n/a
I noticed something interesting while I was doing some JavaScript.
Lets say I have the code below (simplified greatly from what I have
but it's just about the same).

var objs = {'foo' : {}, 'bar':{}, 'baz':{}};

for (var i in objs) {
objs[i].o = {};
objs[i].o.method = function() {
alert(i);
};
}

objs.foo.o.method(); // alerts baz
objs.bar.o.method(); // alerts baz
objs.baz.o.method(); // alerts baz

all three statements above will alert baz, even though the code's
logic should have it alert foo, bar, baz. Can someone explain why that
happens. Also, how would I fix that statement above to work as I
intended to? Thanks.

Jun 17 '07 #1
Share this Question
Share on Google+
5 Replies


P: n/a
On Jun 17, 12:32 pm, Jang <jangc...@gmail.comwrote:
I noticed something interesting while I was doing some JavaScript.
Lets say I have the code below (simplified greatly from what I have
but it's just about the same).

var objs = {'foo' : {}, 'bar':{}, 'baz':{}};

for (var i in objs) {
objs[i].o = {};
objs[i].o.method = function() {
alert(i);
};

}

objs.foo.o.method(); // alerts baz
objs.bar.o.method(); // alerts baz
objs.baz.o.method(); // alerts baz

all three statements above will alert baz, even though the code's
logic should have it alert foo, bar, baz. Can someone explain why that
happens. Also, how would I fix that statement above to work as I
intended to? Thanks.
This definitely seems bizarre at first and this is closure related
issue. The short explaination is that when alert(i) is run it looks
inside the function you have written above and doesn't find an "i"
variable. So it continues up it's lookup chain to find the first "i".
When that for loop finished running the value of "i" was baz.

You are going to think it is pretty odd but you want to be writing
this...

var objs = {'foo' : {}, 'bar':{}, 'baz':{}};

for (var i in objs) {
objs[i].o = {};
objs[i].o.method = (function(i) {return function() {
alert(i);
};})(i);
}

objs.foo.o.method(); // alerts baz
objs.bar.o.method(); // alerts baz
objs.baz.o.method(); // alerts baz
After you figure out how this works and use this for a while you will
be glad it works this way :)

Unfortunately I don't know which video it was but if you watch the
Douglas Crockford videos on the Yahoo! UI Theater <URL:
http://developer.yahoo.com/yui/theater/he discusses exactly this
issue. I think it is in one of the three videos called "Advanced
JavaScript". All of Douglas's videos are worth watching to get a sense
of how one experienced JavaScript user does things.

Since you are using alerts I'm just going to mention it just in
case...you know about the Firefox extension Firebug, yes? <URL:
http://getfirebug.comand then you can use console.log().

Peter

Jun 17 '07 #2

P: n/a
On Jun 17, 5:18 pm, Peter Michaux <petermich...@gmail.comwrote:
On Jun 17, 12:32 pm, Jang <jangc...@gmail.comwrote:
I noticed something interesting while I was doing some JavaScript.
Lets say I have the code below (simplified greatly from what I have
but it's just about the same).
var objs = {'foo' : {}, 'bar':{}, 'baz':{}};
for (var i in objs) {
objs[i].o = {};
objs[i].o.method = function() {
alert(i);
};
}
objs.foo.o.method(); // alerts baz
objs.bar.o.method(); // alerts baz
objs.baz.o.method(); // alerts baz
all three statements above will alert baz, even though the code's
logic should have it alert foo, bar, baz. Can someone explain why that
happens. Also, how would I fix that statement above to work as I
intended to? Thanks.

This definitely seems bizarre at first and this is closure related
issue. The short explaination is that when alert(i) is run it looks
inside the function you have written above and doesn't find an "i"
variable. So it continues up it's lookup chain to find the first "i".
When that for loop finished running the value of "i" was baz.

You are going to think it is pretty odd but you want to be writing
this...

var objs = {'foo' : {}, 'bar':{}, 'baz':{}};

for (var i in objs) {
objs[i].o = {};
objs[i].o.method = (function(i) {return function() {
alert(i);
};})(i);

}

objs.foo.o.method(); // alerts baz
objs.bar.o.method(); // alerts baz
objs.baz.o.method(); // alerts baz

After you figure out how this works and use this for a while you will
be glad it works this way :)

Unfortunately I don't know which video it was but if you watch the
Douglas Crockford videos on the Yahoo! UI Theater <URL:http://developer.yahoo.com/yui/theater/he discusses exactly this
issue. I think it is in one of the three videos called "Advanced
JavaScript". All of Douglas's videos are worth watching to get a sense
of how one experienced JavaScript user does things.

Since you are using alerts I'm just going to mention it just in
case...you know about the Firefox extension Firebug, yes? <URL:http://getfirebug.comand then you can use console.log().
Actually right after I posted, I figured out I can fix it using the
exact method you wrote. I was hoping if there was a "cleaner"
solution. :)

But as I read your post and thought about I think I'm beginning to
understand why that happens. The anonymous function seems to be
evaluated at run time rather than at compile time. And during runtime,
the latest value of i is going to be 'baz.'

Jun 17 '07 #3

P: n/a
Peter Michaux wrote:
On Jun 17, 12:32 pm, Jang <jangc...@gmail.comwrote:
>I noticed something interesting while I was doing some JavaScript.
Lets say I have the code below (simplified greatly from what I have
but it's just about the same).

var objs = {'foo' : {}, 'bar':{}, 'baz':{}};

for (var i in objs) {
objs[i].o = {};
objs[i].o.method = function() {
alert(i);
};

}

objs.foo.o.method(); // alerts baz
objs.bar.o.method(); // alerts baz
objs.baz.o.method(); // alerts baz

all three statements above will alert baz, even though the code's
logic should have it alert foo, bar, baz. Can someone explain why that
happens. Also, how would I fix that statement above to work as I
intended to? Thanks.

This definitely seems bizarre at first and this is closure related
issue. The short explaination is that when alert(i) is run it looks
inside the function you have written above and doesn't find an "i"
variable. So it continues up it's lookup chain to find the first "i".
When that for loop finished running the value of "i" was baz.

You are going to think it is pretty odd but you want to be writing
this...

var objs = {'foo' : {}, 'bar':{}, 'baz':{}};

for (var i in objs) {
objs[i].o = {};
objs[i].o.method = (function(i) {return function() {
alert(i);
};})(i);
}
This is basically creating closures, right?
objs.foo.o.method(); // alerts baz
objs.bar.o.method(); // alerts baz
objs.baz.o.method(); // alerts baz
I think you meant:

objs.foo.o.method(); // alerts foo
objs.bar.o.method(); // alerts bar
objs.baz.o.method(); // alerts baz

;)
After you figure out how this works and use this for a while you will
be glad it works this way :)

Unfortunately I don't know which video it was but if you watch the
Douglas Crockford videos on the Yahoo! UI Theater <URL:
http://developer.yahoo.com/yui/theater/he discusses exactly this
issue. I think it is in one of the three videos called "Advanced
JavaScript". All of Douglas's videos are worth watching to get a sense
of how one experienced JavaScript user does things.

Since you are using alerts I'm just going to mention it just in
case...you know about the Firefox extension Firebug, yes? <URL:
http://getfirebug.comand then you can use console.log().
--
-Lost
Remove the extra words to reply by e-mail. Don't e-mail me. I am
kidding. No I am not.
Jun 18 '07 #4

P: n/a
On Jun 17, 7:16 pm, -Lost <maventheextrawo...@techie.comwrote:
Peter Michaux wrote:
On Jun 17, 12:32 pm, Jang <jangc...@gmail.comwrote:
I noticed something interesting while I was doing some JavaScript.
Lets say I have the code below (simplified greatly from what I have
but it's just about the same).
var objs = {'foo' : {}, 'bar':{}, 'baz':{}};
for (var i in objs) {
objs[i].o = {};
objs[i].o.method = function() {
alert(i);
};
}
objs.foo.o.method(); // alerts baz
objs.bar.o.method(); // alerts baz
objs.baz.o.method(); // alerts baz
all three statements above will alert baz, even though the code's
logic should have it alert foo, bar, baz. Can someone explain why that
happens. Also, how would I fix that statement above to work as I
intended to? Thanks.
This definitely seems bizarre at first and this is closure related
issue. The short explaination is that when alert(i) is run it looks
inside the function you have written above and doesn't find an "i"
variable. So it continues up it's lookup chain to find the first "i".
When that for loop finished running the value of "i" was baz.
You are going to think it is pretty odd but you want to be writing
this...
var objs = {'foo' : {}, 'bar':{}, 'baz':{}};
for (var i in objs) {
objs[i].o = {};
objs[i].o.method = (function(i) {return function() {
alert(i);
};})(i);
}

This is basically creating closures, right?
Yes
objs.foo.o.method(); // alerts baz
objs.bar.o.method(); // alerts baz
objs.baz.o.method(); // alerts baz

I think you meant:

objs.foo.o.method(); // alerts foo
objs.bar.o.method(); // alerts bar
objs.baz.o.method(); // alerts baz

;)
I'm supposed to update comments too? shesh.

Peter

Jun 18 '07 #5

P: n/a
Peter Michaux wrote:
On Jun 17, 7:16 pm, -Lost <maventheextrawo...@techie.comwrote:
>Peter Michaux wrote:
>>On Jun 17, 12:32 pm, Jang <jangc...@gmail.comwrote:
I noticed something interesting while I was doing some JavaScript.
Lets say I have the code below (simplified greatly from what I have
but it's just about the same).
var objs = {'foo' : {}, 'bar':{}, 'baz':{}};
for (var i in objs) {
objs[i].o = {};
objs[i].o.method = function() {
alert(i);
};
}
objs.foo.o.method(); // alerts baz
objs.bar.o.method(); // alerts baz
objs.baz.o.method(); // alerts baz
all three statements above will alert baz, even though the code's
logic should have it alert foo, bar, baz. Can someone explain why that
happens. Also, how would I fix that statement above to work as I
intended to? Thanks.
This definitely seems bizarre at first and this is closure related
issue. The short explaination is that when alert(i) is run it looks
inside the function you have written above and doesn't find an "i"
variable. So it continues up it's lookup chain to find the first "i".
When that for loop finished running the value of "i" was baz.
You are going to think it is pretty odd but you want to be writing
this...
var objs = {'foo' : {}, 'bar':{}, 'baz':{}};
for (var i in objs) {
objs[i].o = {};
objs[i].o.method = (function(i) {return function() {
alert(i);
};})(i);
}
This is basically creating closures, right?

Yes
>>objs.foo.o.method(); // alerts baz
objs.bar.o.method(); // alerts baz
objs.baz.o.method(); // alerts baz
I think you meant:

objs.foo.o.method(); // alerts foo
objs.bar.o.method(); // alerts bar
objs.baz.o.method(); // alerts baz

;)

I'm supposed to update comments too? shesh.
Haha. Well, I figured you pasted it anew, you would probably update it
to reflect your changes. ;)

--
-Lost
Remove the extra words to reply by e-mail. Don't e-mail me. I am
kidding. No I am not.
Jun 18 '07 #6

This discussion thread is closed

Replies have been disabled for this discussion.