Fli*_*sey 13 javascript lua closures scope
为什么这两个看似相同的代码片段在Javascript和Lua中表现不同?
LUA:
function main()
local printFunctions={}
local i,j
for i=1,10 do
local printi = function()
print(i)
end
printFunctions[i]=printi
end
for j=1,10 do
printFunctions[j]()
end
end
main()
Run Code Online (Sandbox Code Playgroud)
使用Javascript:
function main()
{
var printFunctions=[]
var i,j;
for(i=0;i<10;i++)
{
var printi = function()
{
console.log(i);
}
printFunctions[i]=printi;
}
for(j=0;j<10;j++)
{
printFunctions[j]();
}
}
main()
Run Code Online (Sandbox Code Playgroud)
Lua中的示例打印0 1 2 3 4 5 6 7 8 9,但Javascript中的示例打印10 10 10 10 10 10 10 10 10 10.任何人都可以解释Javascript和Lua中导致这种情况发生的闭包之间的区别吗?我来自Javascript背景,所以请关注Lua方面.
我试图在我的博客上解释这一点,但我不确定我的解释是否正确,所以任何澄清都将不胜感激.
编辑
谢谢大家,现在我明白了.这个稍微修改过的版本的Lua代码按预期打印10,10,10,10,10,10,10,10,10,10
function main()
local printFunctions={}
local i,j,k
for i=1,10 do
k=i
local printi = function()
print(k)
end
printFunctions[i]=printi
end
for j=1,10 do
printFunctions[j]()
end
end
main()
Run Code Online (Sandbox Code Playgroud)
它简单如下:
Lua local变量的范围仅限于最近的do-end块,而声明的JavaScript变量var的范围限定为最近的函数边界.闭包通过将它们放在函数中的各自范围内来解决问题,解决了范围问题.
关于您local i, j在外部范围内的问题,Lua中的for语句创建了在块作用域中使用的计数器的范围,即使外部作用域中存在变量声明也是如此.文件说(参考):
循环变量v是循环的局部变量; 你不能在结束后使用它的价值或被打破.如果需要此值,请在断开或退出循环之前将其分配给另一个变量.
这意味着var初始化是针对for循环范围进行的,因此放置local i, j在外部范围内无效.这可以在Lua的for语句中看到,在文档中给出:
do
local var, limit, step = tonumber(e1), tonumber(e2), tonumber(e3)
if not (var and limit and step) then error() end
while (step > 0 and var <= limit) or (step <= 0 and var >= limit) do
local v = var
block
var = var + step
end
end
Run Code Online (Sandbox Code Playgroud)
但是,JavaScript的声明差别很大(参考):
IterationStatement : for ( var VariableDeclarationListNoIn ; Expressionopt ; Expressionopt ) Statement
因为for循环的声明与任何普通变量声明相同,所以它等同于将它放在循环之外,与Lua for循环的工作方式大不相同.ECMAScript的下一个版本(ES6)计划引入let关键字,在for循环中,它与Lua for for循环的工作方式具有相似的含义:
for (let i = 0; i < 10; ++i) setTimeout(function () { console.log(i); }, 9); // 0,1,2,3,4,5,6,7,8,9
for (var i = 0; i < 10; ++i) setTimeout(function () { console.log(i); }, 9); // 10,10,10,10,10,10,10,10,10,10
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
411 次 |
| 最近记录: |