这是一段代码:
var data = [ 'data1', 'data2', 'data3' ];
for (var i = 0; i < data.length; i++) {
var x = data[i];
setTimeout(function() {
console.log(x);
}, i * 100);
}
输出是'data3'的3倍。我的问题是为什么?
据我所知,循环结束后将调用所有3个日志方法,变量i将等于3,但是!
我在循环中定义了x变量。我希望在每次循环迭代时,可以在本地重新创建此变量,以便在调用每个console.log(x)方法时,它们引用存储在内存中的3个不同变量。
但它看起来像代码:
var x = data[i];
更新相同的变量,而不是重新创建它。
有人可以解释这种行为吗?
答案 0 :(得分:2)
使用var
声明的变量具有函数范围。这意味着整个函数中只有一个变量具有该名称。 var
声明的位置无关紧要。函数声明隐式“提升”到函数的顶部,是整个函数可用的单个变量。
您的代码与此相同,它说明了为什么x
所有setTimeout()
次呼叫共享var data = [ 'data1', 'data2', 'data3' ];
var x;
for (var i = 0; i < data.length; i++) {
x = data[i];
setTimeout(function() {
console.log(x);
}, i * 100);
}
只有一个实例:
x
您可以通过在适当的位置引入一个函数来解决您的问题,以便在其自己的函数范围内唯一捕获var data = [ 'data1', 'data2', 'data3' ];
for (var i = 0; i < data.length; i++) {
(function(x) {
setTimeout(function() {
console.log(x);
}, i * 100);
)}(data[i]);
}
的每个值:
let
在最新的ES6中,变量可以使用let
声明,然后它们将具有您想要的块范围。因此,在最新的浏览器或node.js中,您可以使用var data = [ 'data1', 'data2', 'data3' ];
for (var i = 0; i < data.length; i++) {
let x = data[i];
setTimeout(function() {
console.log(x);
}, i * 100);
}
,它将具有所需的块范围:
function stopTimer() {
clearTimeout(timerID);
timerID = null;
timerObj.value = save;
var theBody = document.getElementById("theBody");
setTimeout(function () { theBody.className = "white"; }, 0);
setTimeout(function () { theBody.className = "red"; }, 250);
setTimeout(function () { theBody.className = "white"; }, 500);
setTimeout(function () { theBody.className = "red"; }, 750);
setTimeout(function () { theBody.className = "white"; }, 1000);
setTimeout(function () { theBody.className = "red"; }, 1250);
setTimeout(function () { theBody.className = "white"; }, 1500);
setTimeout(function () { theBody.className = "red"; }, 1750);
setTimeout(function () { theBody.className = "white"; }, 2000);
setTimeout(function () { theBody.className = "white"; }, 2250);
setTimeout(function () { theBody.className = "red"; }, 2500);
setTimeout(function () { theBody.className = "white"; }, 2750);
setTimeout(function () { theBody.className = "red"; }, 3000);
setTimeout(function () { theBody.className = "white"; }, 3250);
setTimeout(function () { theBody.className = "red"; }, 3500);
setTimeout(function () { theBody.className = "white"; }, 3750);
setTimeout(function () { theBody.className = "red"; }, 4000);
setTimeout(function () { theBody.className = "white"; }, 4250);
var audio = document.createElement("audio");
audio.src = "alarm.mp3";
theBody.appendChild(audio);
audio.setAttribute("id", "audio");
audio.play();
setTimeout(function () {
audio.pause();
}, 6000);``