开发者

Need clarification on the loop problem in closures

so I'm understanding closures and circular references (I hope), but one aspect is the much reported closure within a loop which seems to cause much ado. I need clarification on it. The code I'm looking at is:

function showHelp(help) {
  document.getElementById('help').innerHTML = help;
}

function getHelp(help) {
  alert(help); 
  // only to show value of "help" at this point, also to prove that "getHelp()" is being called even
  // though the onfocus wasn't used

  return function() {
    showHelp(help);
  }
}

function setupHelp(){
  var helpText = [
    {'id':"email",'help':"Your email address"},
    {'id':"name",'help':"Your full name"},
    {'id':"age",'help':"Your real age"}
  ];

  for(var i=0;i<helpText.length;i++){
    var item = helpText[i];
    alert(item.help);
    // only to show value of "help" at this point, also to prove that "getHelp()" is
    // being called even though the onfocus wasn't used
    document.getElementById(item.id).onfocus = getHelp(item.help);
  }
}

The premise here being that you have three input fields and focusing them will return a helpful hint (as seen on the MDC article). But, here's the crux of my lack of grasp: If you put an alert (so as to test) in the "getHelp()" function, and put one in the开发者_StackOverflow "setupHelp()" function, just before you set bind the event handler to a reference to the dom element, you'll see that, on loading the page, the loop runs, then the getHelp() function, then the loop, then the getHelp() function, etc, until the end of the loop. So if the getHelp() function is bound to the onfocus event handler, and you don't even focus the input fields, howe can the getHelp() function run?? And how does JAvaScript store all possible outcomes from that one little loop? :S

Any help you could provide would really help, this is mind boggling right now. I'm sure it'll just click one of these days, but I'm impatient. :P

Tom.


So if the getHelp() function is bound to the onfocus event handler, and you don't even focus the input fields, howe can the getHelp() function run?? And how does JAvaScript store all possible outcomes from that one little loop?

This is the crux of your question, and the answer lies here:

for(var i=0;i<helpText.length;i++){
    var item = helpText[i];
    alert(item.help);
    // only to show value of "help" at this point, also to prove that "getHelp()" is
    // being called even though the onfocus wasn't used
    document.getElementById(item.id).onfocus = getHelp(item.help);
}

That's how the JavaScript interpreter stores all of the possible outcomes: Because you told it what they were. You're calling getHelp, which is generating a function, and then returning that function.

How this works is much simpler than it seems. :-) I go into it a fair bit here, but basically: When you call a function, something called an execution context is created. That's an object (JavaScript is massively object-oriented, right down to the interpreter level). In that execution context object, there's something called the variable object. It holds all of the variables for the execution context, as properties. This includes the arguments to the function, all the vars within the function, and any declared functions as well (you don't have any declared functions in your example, so we can ignore that; you have only function expressions, which is fine). Any function declared or defined by expression within an execution context has an enduring reference to the variable object for that execution context, and uses it to resolve variable references when it's called.

So: In your loop, when you call getHelp, an object is created storing the data related to that call. That object is bound to the function that you're creating within the call and storing on the onfocus handler (that's the data that the function closes over [which is why it's called a closure]). When/if the handler is called, that's how the references that function holds are resolved, against properties on that object.

More reading: Closures are not complicated


actually, you're assigning the result of getHelp(help) to your onfocus event, so it's totally normal that both alerts shows, since getHelp is executed to give its result.

If you put the alert in the returner function, I'm pretty sure you won't see it :

function getHelp(help){
    return function(){
        alert(help); 
        showHelp(help);
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜