npo*_*cop 20 javascript closures node.js
除了标准之外,Javascript中的变量捕获是否有明确的来源(阅读标准是一种痛苦)?
在下面的代码i中按值复制:
for (var i = 0; i < 10; i++)
{
(function (i)
{
process.nextTick(function ()
{
console.log(i)
})
}) (i)
}
Run Code Online (Sandbox Code Playgroud)
所以打印1..10.process.nextTick是setTimeout(f,0)节点的模拟.
但在下一个代码中我似乎没有被复制:
for (var i = 0; i < 10; i++)
{
var j = i
process.nextTick(function ()
{
console.log(j)
})
}
Run Code Online (Sandbox Code Playgroud)
它打印9次10次.为什么?我对参考/一般文章比对解释捕获的具体情况更感兴趣.
在 JavaScript 中,函数包含在其自身范围之外定义的变量,这样它们就具有对该变量的“活”引用,而不是其在任何特定时间的值的快照。
因此,在第二个示例中,您创建了十个匿名函数(在 中process.nextTick(function(){...})),其中包含变量j(和i,在创建匿名函数时它们始终具有相同的值)。这些函数中的每一个都在外部 for 循环完全运行之后(即调用每个函数时)j使用的值。也就是说,首先你的 for 循环完全运行,然后你的匿名函数运行并使用 的值,该值已经设置为 10!j=i=10j
在你的第一个例子中,情况有点不同。通过将调用包装process.nextTick(...)在它自己的匿名函数中,并通过调用包装函数将 的值绑定i到函数局部范围(并顺便将旧变量隐藏i到函数参数中),您可以捕获当时i变量的值,而不是保留其值在内部匿名函数的封装中发生变化的封闭引用。ii
为了稍微澄清您的第一个示例,请尝试更改匿名包装函数以使用名为x( (function (x) { process.nextTick(...); })(i)) 的参数。在这里我们清楚地看到,在调用匿名函数时x获取值,因此它将获取 for 循环中的每个值 (1..10)。i
它是在你的第二个例子中被复制(或分配)的,它只是一个变量的副本,j它将具有它最后的值,它将是9(你的for循环的最后一次转换).您需要一个新的函数闭包来为每个for循环转换创建一个新的变量副本.你的第二个例子只有一个变量,for它对你的循环的所有转速都是通用的 ,因此它只能有一个值.
我不知道有关这个主题的任何明确的文章.
javascript中的变量的范围是功能级别.javascript中没有块作用域.因此,如果您想为for循环的每次转换使用新版本的变量,则必须使用新函数(创建函数闭包)以在每次for循环时捕获该新值.如果没有函数闭包,那么一个变量只有一个值,该值对于该变量的所有用户都是通用的.
当你声明一个变量,比如你var j = i;在函数开头以外的某个位置时,javascript将定义提升到函数的顶部,你的代码就等同于:
var j;
for (var i = 0; i < 10; i++)
{
j = i;
process.nextTick(function ()
{
console.log(j)
})
}
Run Code Online (Sandbox Code Playgroud)
variable hoisting如果你想了解更多关于它的话,这就是你可以称之为Google的术语.但是,重点是只有函数作用域,因此在函数中任何地方声明的变量实际上在函数顶部声明一次,然后分配给函数中的任何位置.
| 归档时间: |
|
| 查看次数: |
12848 次 |
| 最近记录: |