【问题标题】:how values are passed to callbacks in javascript如何将值传递给javascript中的回调
【发布时间】:2017-07-10 12:21:16
【问题描述】:

我想了解javascript引擎如何以及何时将值传递给回调函数,我尝试过调试和在线查找但无法找到确切答案,请考虑以下示例:

for(var i = 0; i < 4; i++) {
    console.log("outside callback " + i + " ");

    setTimeout(function test(){
      console.log("inside callback " + i + " ");
    },100);
}

这会打印以下输出

外部回调 0

外部回调 1

外部回调 2

外部回调 3

内部回调 4

内部回调 4

内部回调 4

内部回调 4

如果我只是使用 let 关键字更改 i 变量的声明,如下所示:

for(let i = 0; i < 4; i++) {
    console.log("outside callback " + i + " ");
    
    setTimeout(function test(){
       console.log("inside callback " + i + " ");
    },100);
}

结果如下:

外部回调 0

外部回调 1

外部回调 2

外部回调 3

内部回调 0

内部回调 1

内部回调 2

内部回调 3

在 Chrome 中调试时,它在第一个示例中显示 i 作为测试函数的闭包范围,在第二个示例中显示块范围。

【问题讨论】:

  • 变量范围与“当javascript引擎将值传递给回调函数时”有什么关系?

标签: javascript closures v8


【解决方案1】:

这与一个关于 JavaScript closure inside loops – simple practical example 的常见问题有关,该问题详细说明了为什么在循环中创建的内部回调函数,使用 var 声明的变量具有它们在循环结束时达到的值:虽然它们可能有在设置回调时保存不同的值,在执行回调时,异步,一段时间后,循环早已结束,并将变量留在闭包中,其中包含循环完成时它们保存的值。

从 ECMAScript 版本 6 开始,使用 let 声明的变量是块范围的,不能在定义它们的代码块之外访问。 此外for 循环控制语句中定义的变量接受特殊处理。

  1. 它们的作用域是for 循环体,而不是包含for 循环的代码块。
  2. 为循环的每次迭代创建let 变量的新绑定。这意味着每次迭代都可以有自己的一组变量值,保存在为迭代创建的词法环境记录中,可以在闭包中使用并由循环中定义的回调函数访问。

  3. 每个词法环境记录中循环计数器的值旨在使多个环境记录的使用在很大程度上透明:

    for( part1; part2; part3) {
        // loop body code
    }
    
    • 在第一次迭代中,letfor 语句中定义的变量具有执行part1part2 后的值。
    • 在随后的迭代中,它们的值是通过将它们在当前迭代的环境记录中的值初始化为它们在上一次迭代结束时的值来确定的,然后在@987654335 中执行part3part2上面的@声明。
    • for 循环体中声明的回调函数访问在设置回调的迭代的结束 保存的let 定义变量的值,不包括 评估 for 语句的 part3 的副作用。

【讨论】:

    【解决方案2】:

    其实是因为varaibles的作用域是用let和var声明的,而不仅仅是javascript的闭包属性。

    【讨论】:

    • 你能解释一下这里到底发生了什么
    • 我希望这个post 非常清楚地解释了使用全局命名空间的问题。
    猜你喜欢
    • 2018-03-01
    • 2016-11-17
    • 2017-01-26
    • 1970-01-01
    • 2012-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-07
    相关资源
    最近更新 更多