1

Possible Duplicate:
Event handlers inside a Javascript loop - need a closure?

I have been trying to get this to work for a while and decided to just ask.

I have the following:

function doSomething(var1, var2) {
 dojo.xhrGet({
 url:"somUrl",
 content: {value1:var1,value2:var2},
 preventCache: true,
 handleAs:"json",
 load: function(response){
 for(var i in response.myObject) {
 var listItem = new dojox.mobile.ListItem({
 label: response.myObject[i].name,
 rightText: response.myObject[i].value,
 clickable: true, 
 onClick: function() {
 customFunction(response.myObject[i]);
 this.transitionTo("someScreen");
 } 
 });
 myList.addChild(listItem);
 } 
 },
 error:function(e){alert(e);}
 });
}
doSomething(myVal1, myVal2);

The line that says customFunction(response.myObject[i]); always returns the last object in the myObject arrray.

Can someone help me with the syntax so I can make this work correctly? I've been reading about js closures and callbacks but I just can't get it to work.

Thanks

asked Nov 16, 2011 at 20:34
1
  • 2
    You can save yourself a lot of time by paying attention to the possible duplicate questions that Stackoverflow automatically shows you when you're trying to ask a new one. This issue in particular is covered by many many previous questions. Commented Nov 16, 2011 at 20:37

2 Answers 2

3

You need an additional wrapper function

onClick: (function(obj) {
 return function() {
 customFunction(obj);
 this.transitionTo("someScreen");
 };
})(response.myObject[i])

See this answer for an explanation:

JavaScript's scopes are function-level, not block-level, and creating a closure just means that the enclosing scope gets added to the lexical environment of the enclosed function.

After the loop terminates, the function-level variable i has the value 5 [note: or, in this case, the name of the last property in response.myObject], and that's what the inner function 'sees'.

answered Nov 16, 2011 at 20:40
Sign up to request clarification or add additional context in comments.

Comments

2

You need to ensure that i is contained in a closure in each iteration of the for-loop:

[...]
 load: function(response){
 for(var i in response.myObject) {
 var listItem = new dojox.mobile.ListItem({
 label: response.myObject[i].name,
 rightText: response.myObject[i].value,
 clickable: true, 
 onClick: (function(inner) {
 return function (clickEvent) {
 customFunction(response.myObject[inner]);
 this.transitionTo("someScreen");
 }
 }(i)) 
 });
 myList.addChild(listItem);
 } 
 }
 [...]
answered Nov 16, 2011 at 20:38

4 Comments

Now if only JS had better scoping options defined in the core language.
@ChaosPandion: "JS 1.7" has let blocks and statements
@newacct: it's also in the ES.next draft ( wiki.ecmascript.org/doku.php?id=harmony:specification_drafts ), ie the next ECMA edition will probably make it official...
@newacct - I am aware of let in JavaScript. What I should have said was ECMAScript. Logically you really can't use let unless you are targeting JavaScript only.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.