Ответ 1
Это так просто, как следующее:
Переменные Lua local
привязаны только к ближайшему блоку do-end
, а переменные JavaScript, объявленные с помощью var
, привязаны к ближайшим границам функций. Замыкания преодолевают эту точку, помещая их в свою собственную область действия в функцию, решая проблему области.
Что касается вопроса о том, что local i, j
находится во внешней области, оператор for в Lua создает область действия счетчика, используемого в области блока, даже если во внешней области есть объявление переменной. В документации указано (ссылка):
Переменная цикла v является локальной для цикла; вы не можете использовать его значение после конца или сломано. Если вам нужно это значение, назначьте его другой переменной перед тем, как выходить из цикла или выходить из него.
Это означает, что инициализация var
сделана локальной для области цикла for, поэтому размещение local i, j
во внешней области не влияет. Это можно увидеть в эквиваленте инструкции Lua для инструкции, приведенной в документации:
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
Однако JavaScript для оператора значительно отличается (ссылка):
IterationStatement : for ( var VariableDeclarationListNoIn ; Expressionopt ; Expressionopt ) Statement
Поскольку объявление цикла for совпадает с объявлением любой обычной переменной, оно эквивалентно размещению его вне цикла, что значительно отличается от того, как работает цикл Lua for. Следующая версия ECMAScript (ES6) планирует ввести ключевое слово let
, которое в цикле for будет иметь аналогичное значение для работы Lua for loop:
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