473,473 Members | 2,002 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

Please explains why this happens w/ anon functions

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
5 1225
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
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
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
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
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

35
by: wired | last post by:
Hi, I've just taught myself C++, so I haven't learnt much about style or the like from any single source, and I'm quite styleless as a result. But at the same time, I really want nice code and I...
1
by: Az Tech | last post by:
Hi people, (Sorry for the somewhat long post). I request some of the people on this group who have good experience using object-orientation in the field, to please give some good ideas for...
3
by: david | last post by:
I found my web.config file always in lock mode, when I tried to modify it, I ofter got "Can not create web.config" error. I had to reboot my machine, and before I accessed any site I can modify it....
1
by: David Van D | last post by:
Hi there, A few weeks until I begin my journey towards a degree in Computer Science at Canterbury University in New Zealand, Anyway the course tutors are going to be teaching us JAVA wth bluej...
8
by: anon | last post by:
Hi, Newbie to Python and I have a question please. I am using Windows XP, SPE 0.8.2.a and Python24. I have done this: import sys print sys.path no problem there, sys imports just fine. ...
118
by: 63q2o4i02 | last post by:
Hi, I've been thinking about Python vs. Lisp. I've been learning Python the past few months and like it very much. A few years ago I had an AI class where we had to use Lisp, and I absolutely...
1
by: glenn123 | last post by:
Hi, i am just about out of time to produce a working jukebox which has to perform these functions: to play music files when a track is chosen from a list which when the user presses the change genre...
7
by: mohammaditraders | last post by:
Write a program which overloads a binary Minus (+) operator, The program will contain a class Matrix, This class will contain a private data member Array which store int values. The class will...
2
by: Tim | last post by:
Dim Animals as String() = {"cat", "dog", "mouse", "rat"} Can the Exists or Find method be used to determine if the Animals array contains "mouse" ? If Animals.Exists(.... or ...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.