javascript - javascript 闭包中的环境范围

标签 javascript closures

遇到Mozila developer network中描述的关闭常见错误

it doesn't work as expected. No matter what field you focus on, the message about your age will be displayed.

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);
    }
  }
}

setupHelp();

它确实给出了解决方案。这是添加另一个闭包。

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

function makeHelpCallback(help) {
  return function() {
    showHelp(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 = makeHelpCallback(item.help);
  }
}

setupHelp(); 

MDN给出的解释是因为第二种方案创建了3个环境。

谁能给我解释一下,“环境”阶段是什么意思,以及我如何知道它的范围?

最佳答案

当您在函数中使用变量名称时,JavaScript 解释器首先检查该变量是否为函数内的局部变量。如果不存在这样的局部变量,则它会向上遍历到外部作用域以查找该变量。 (定义函数时,它可以访问作用域链——作用域的层次结构,从定义该函数的外部函数的作用域开始,一直到包含该函数的函数等)

这里,匿名onfocus处理函数使用变量标识符itemitem 不是函数内的局部变量,因此当执行处理程序时,JavaScript 必须向上遍历下一个外部作用域,在其中找到 item (如 中定义)安装帮助。您为每个项目定义了一个处理函数;然而,这些处理函数的所有都在外部作用域中持有对item相同引用。每当调用这些函数中的任何一个时,JavaScript 都会为 item 查找相同的值,该值是 for 循环完成时它所保存的值。

如果有额外的闭包,您可以将 item.help 的当前值作为参数传递给 makeHelpCallback,后者返回一个处理函数。由于 JavaScript 按值传递变量,因此每个处理函数现在都有一个单独的外部作用域,并具有不同的 help 值。

关于javascript - javascript 闭包中的环境范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14114521/

相关文章:

javascript - 即使Internet Explorer浏览器在设置中禁用了音频,我们也可以通过Javascript编码播放音频吗?

javascript - 定位当前选中的单选按钮

javascript - 更好地理解循环内的 JavaScript 闭包

swift - Realm IOS 类型转换结果关闭

javascript - 如何清除 Angular 中组合框的选定值

javascript - 将 Jquery 自动完成的值检索到 Ajax 调用中

javascript - 关闭次数? (语义澄清)

javascript - JavaScript 中的作用域和闭包问题

javascript - 通过 JavaScript 或 Linq 设置 JSON 集合字符串的格式

java - Closure 示例的处理流程 | Java 8