本文介绍了Javascript 闭包 - 可变范围问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读 Mozilla 开发人员关于闭包的网站,我注意到在他们的常见错误示例中,他们有以下代码:

I'm reading the Mozilla developer's site on closures, and I noticed in their example for common mistakes, they had this code:

<p id="help">Helpful notes will appear here</p>
<p>E-mail: <input type="text" id="email" name="email"></p>
<p>Name: <input type="text" id="name" name="name"></p>
<p>Age: <input type="text" id="age" name="age"></p>

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

function setupHelp() {
  var helpText = [
      {'id': 'email', 'help': 'Your e-mail address'},
      {'id': 'name', 'help': 'Your full name'},
      {'id': 'age', 'help': 'Your age (you must be over 16)'}
    ];

  for (var i = 0; i < helpText.length; i++) {
    var item = helpText[i];
    document.getElementById(item.id).onfocus = function() {
      showHelp(item.help);
    }
  }
}

他们说对于 onFocus 事件,代码只会显示最后一项的帮助,因为分配给 onFocus 事件的所有匿名函数都有一个围绕 'item' 变量的闭包,这是有道理的,因为在 JavaScript 变量中没有块作用域.解决方案是改用'let item = ...',因为它具有块作用域.

and they said that for the onFocus event, the code would only show help for the last item because all of the anonymous functions assigned to the onFocus event have a closure around the 'item' variable, which makes sense because in JavaScript variables do not have block scope. The solution was to use 'let item = ...' instead, for then it has block scope.

然而,我想知道为什么不能在 for 循环的正上方声明var item"?然后它有 setupHelp() 的作用域,每次迭代你都给它分配一个不同的值,然后它会在闭包中被捕获为它的当前值......对吗?

However, what I wonder is why couldn't you declare 'var item' right above the for loop? Then it has the scope of setupHelp(), and each iteration you are assigning it a different value, which would then be captured as its current value in the closure... right?

推荐答案

这是因为在对 item.help 求值时,循环将完全完成.相反,您可以使用闭包来做到这一点:

Its because at the time item.help is evaluated, the loop would have completed in its entirety. Instead, you can do this with a closure:

for (var i = 0; i < helpText.length; i++) {
   document.getElementById(helpText[i].id).onfocus = function(item) {
           return function() {showHelp(item.help);};
         }(helpText[i]);
}

JavaScript 没有块作用域,但它有函数作用域.通过创建闭包,我们将永久捕获对 helpText[i] 的引用.

JavaScript doesn't have block scope but it does have function-scope. By creating a closure, we are capturing the reference to helpText[i] permanently.

这篇关于Javascript 闭包 - 可变范围问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-23 06:26