让 vs var in javascript
let vs var in javascript
我知道 let 有块作用域而 var 有函数作用域。但是我不明白在这种情况下,使用 let 将如何解决问题
const arr = [1,2,3,4];
for (var i = 0; i < arr.length; i++) {
setTimeout(function() {
console.log(arr[i])
}, 1000);
} // Prints undefined 5 times
const arr = [1,2,3,4];
for (let i = 0; i < arr.length; i++) {
setTimeout(function() {
console.log(arr[i])
}, 1000);
} // Prints all the values correctly
您仍然可以将 var
用于 setTimeout
。您可以使用立即调用的函数表达式 (IIFE) 在 setTimeout
周围创建一个闭包,以便 setTimeout
函数识别 i
的值。
const arr = [1,2,3,4];
for (var i = 0; i < arr.length; i++) {
(function(i){
setTimeout(function() {
console.log(arr[i])
}, 1000)})(i);
}
这都跟变量的作用域有关。让我们尝试将这两个部分包装成函数,并观察输出:
function test() {
// `i` will be declared here, making it a non-for-loop scoped variable
const arr = [1, 2, 3, 4];
for (var i = 0; i < arr.length; i++) {
setTimeout(function() {
console.log(arr[i])
}, 1000);
} // Prints undefined 5 times
}
test();
所以在第一种情况下,i
会被提升,并且由于setTimeout
的异步特性,i
会随着循环结束而立即变为4,无需等待。这将使 arr[i]
指向数组中的 undefined
元素。
在第二种情况下,i
未提升,并且对循环的每次迭代进行范围访问,从而使 i
可准确地用于 console.log
语句。因此结果符合预期:
function test() {
const arr = [1, 2, 3, 4];
for (let i = 0; i < arr.length; i++) {
setTimeout(function() {
console.log(arr[i])
}, 1000);
} // Prints all the values correctly
}
test();
首先,输出将是四次而不是五次(如您的评论中所述)。
我将你的代码粘贴到 Babel REPL 中,这就是我得到的,
"use strict";
var arr = [1, 2, 3, 4];
var _loop = function _loop(i) {
setTimeout(function () {
console.log(arr[i]);
}, 1000);
};
for (var i = 0; i < arr.length; i++) {
_loop(i);
}
你看到 let 现在在内部是如何工作的了吗? :-)
我知道 let 有块作用域而 var 有函数作用域。但是我不明白在这种情况下,使用 let 将如何解决问题
const arr = [1,2,3,4];
for (var i = 0; i < arr.length; i++) {
setTimeout(function() {
console.log(arr[i])
}, 1000);
} // Prints undefined 5 times
const arr = [1,2,3,4];
for (let i = 0; i < arr.length; i++) {
setTimeout(function() {
console.log(arr[i])
}, 1000);
} // Prints all the values correctly
您仍然可以将 var
用于 setTimeout
。您可以使用立即调用的函数表达式 (IIFE) 在 setTimeout
周围创建一个闭包,以便 setTimeout
函数识别 i
的值。
const arr = [1,2,3,4];
for (var i = 0; i < arr.length; i++) {
(function(i){
setTimeout(function() {
console.log(arr[i])
}, 1000)})(i);
}
这都跟变量的作用域有关。让我们尝试将这两个部分包装成函数,并观察输出:
function test() {
// `i` will be declared here, making it a non-for-loop scoped variable
const arr = [1, 2, 3, 4];
for (var i = 0; i < arr.length; i++) {
setTimeout(function() {
console.log(arr[i])
}, 1000);
} // Prints undefined 5 times
}
test();
所以在第一种情况下,i
会被提升,并且由于setTimeout
的异步特性,i
会随着循环结束而立即变为4,无需等待。这将使 arr[i]
指向数组中的 undefined
元素。
在第二种情况下,i
未提升,并且对循环的每次迭代进行范围访问,从而使 i
可准确地用于 console.log
语句。因此结果符合预期:
function test() {
const arr = [1, 2, 3, 4];
for (let i = 0; i < arr.length; i++) {
setTimeout(function() {
console.log(arr[i])
}, 1000);
} // Prints all the values correctly
}
test();
首先,输出将是四次而不是五次(如您的评论中所述)。 我将你的代码粘贴到 Babel REPL 中,这就是我得到的,
"use strict";
var arr = [1, 2, 3, 4];
var _loop = function _loop(i) {
setTimeout(function () {
console.log(arr[i]);
}, 1000);
};
for (var i = 0; i < arr.length; i++) {
_loop(i);
}
你看到 let 现在在内部是如何工作的了吗? :-)