我正在开发Javascript,并使用firefox抓痕板来执行它。我有一个全局索引,我想在我的setTimeout (或任何异步执行的函数)中获取它。我不能使用Array.push作为数据顺序必须保持,就好像它是按顺序执行的。这是我的密码:-
function Demo() {
this.arr = [];
this.counter = 0;
this.setMember = function() {
var self = this;
for(; this.counter < 10; this.counter++){
var index = this.counter;
setTimeout(function(){
self.arr[index] = 'I am John!';
}, 100);
}
};
this.logMember = function() {
console.log(this.arr);
};
}
var d = new Demo();
d.setMember();
setTimeout(function(){
d.logMember();
}, 1000);在这里,我希望我的d.arr有0-9个索引,所有索引都有'I am John!',但是只有第9个索引有'I am John!'。我想,将this.counter保存到index局部变量将获得this.counter的快照。有人能帮我理解我的代码有什么问题吗?
发布于 2014-04-25 13:59:50
本例中的问题与JS中的范围有关。因为没有块作用域,所以它基本上相当于
this.setMember = function() {
var self = this;
var index;
for(; this.counter < 10; this.counter++){
index = this.counter;
setTimeout(function(){
self.arr[index] = 'I am John!';
}, 100);
}
};当然,由于赋值是异步的,循环将运行到完成,将索引设置为9,然后函数在100 is后执行10次。
有几种方法可以做到这一点:
index的当前值在闭包范围中保存为i,并且赋值是正确的。i放入函数中,所以我们可以使用bind的第二个参数,它部分地应用了一个函数,以确保以后用当前索引调用它。我们还可以去掉self = this行,因为我们可以直接绑定调用函数的this值。当然,我们也可以去掉索引变量,直接使用this.counter,使其更加简洁。就我个人而言,我认为第三个解决方案是最好的。它很短,很优雅,而且完全可以满足我们的需要。其他的一切都是为了完成语言当时所不支持的事情。因为我们有bind,所以没有更好的方法来解决这个问题。
发布于 2014-04-25 14:15:17
原因是在启动时间设置超时时,for循环已经完成,索引值为9,所以所有定时器基本上都在设置arr9。
发布于 2014-04-25 14:05:41
前面的答案是正确的,但提供的源代码是错误的,有一个错误的精灵代替了自我。解决办法有效。
另一种没有闭包的方法是将索引参数添加到setTimeout语句中的函数声明中。
function Demo() {
this.arr = new Array();
this.counter = 0;
this.setMember = function() {
var self = this;
for(; this.counter < 10; this.counter++){
var index = this.counter;
setTimeout(function(){
self.arr[index] = 'I am John!';
}(index), 100);
}
};
this.logMember = function() {
console.log(this.arr);
};
}
var d = new Demo();
d.setMember();
setTimeout(function(){
d.logMember();
}, 1000);https://stackoverflow.com/questions/23294903
复制相似问题