Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/388.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript:在setTimeout中使用更改全局变量_Javascript - Fatal编程技术网

Javascript:在setTimeout中使用更改全局变量

Javascript:在setTimeout中使用更改全局变量,javascript,Javascript,我正在使用Javascript并使用firefox scratchpad执行它。我有一个全局索引,我想在我的setTimeout(或异步执行的任何函数)中获取它。我不能使用数组。按,因为数据的顺序必须保持为按顺序执行。这是我的密码:- function Demo() { this.arr = []; this.counter = 0; this.setMember = function() { var self = this; for(;

我正在使用
Javascript
并使用firefox scratchpad执行它。我有一个全局索引,我想在我的
setTimeout
(或异步执行的任何函数)中获取它。我不能使用数组。按,因为数据的顺序必须保持为按顺序执行。这是我的密码:-

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);
函数演示(){
this.arr=[];
这个计数器=0;
this.setMember=函数(){
var self=这个;
对于(;this.counter<10;this.counter++){
var指数=这个计数器;
setTimeout(函数(){
self.arr[index]=“我是约翰!”;
}, 100);
}
};
this.logMember=函数(){
console.log(this.arr);
};
}
var d=新的Demo();
d、 setMember();
setTimeout(函数(){
d、 logMember();
}, 1000);

在这里,我希望我的
d.arr
有0-9个索引,所有索引都有
“我是约翰!”,但只有第9个索引有“我是约翰!”。我想,将
this.counter
保存到
index
局部变量中,将拍摄
this.counter
的快照。有人能帮我理解我的代码有什么问题吗?

设置超时
没有您所期望的
索引的快照。所有超时都会将索引视为最终迭代,因为您的循环在超时触发之前完成。您可以将其包装在闭包中并传入索引,这意味着闭包中的索引将受到保护,不受对全局
索引的任何更改的影响

(function(index){
    setTimeout(function(){
        self.arr[index] = 'I am John!';
    }, 100);
})(index);

本例中的问题与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);
    }
};
  • 使用

    this.setMember=function(){
    对于(;this.counter<10;this.counter++){
    设置超时(功能(i){
    这个。啊[我]=“我是约翰!”;
    }.bind(这个,这个计数器),100);
    }
    };
    
    由于我们所关心的只是将正确类型的
    i
    放入函数中,因此我们可以使用
    bind
    的第二个参数,该参数部分应用函数,以确保稍后使用当前索引调用该函数。我们还可以去掉
    self=this
    行,因为我们可以直接绑定调用的函数的
    this
    值。当然,我们也可以去掉索引变量,直接使用this.counter,使其更加简洁

  • 我个人认为第三种解决方案是最好的。 它短而优雅,完全符合我们的需要。 其他一切都是为了完成该语言当时不支持的事情而进行的黑客攻击。
    因为我们有
    bind
    ,所以没有更好的方法来解决这个问题。

    前面的答案是正确的,但是提供的源代码是错误的,在self中输入了一个错误的elf。这些解决方案是有效的

    另一种没有闭包的方法是只将索引参数添加到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);
    
    函数演示(){
    this.arr=新数组();
    这个计数器=0;
    this.setMember=函数(){
    var self=这个;
    对于(;this.counter<10;this.counter++){
    var指数=这个计数器;
    setTimeout(函数(){
    self.arr[index]=“我是约翰!”;
    }(指数),100);
    }
    };
    this.logMember=函数(){
    console.log(this.arr);
    };
    }
    var d=新的Demo();
    d、 setMember();
    setTimeout(函数(){
    d、 logMember();
    }, 1000);
    
    原因是,在启动settimeout时,for循环已完成执行,索引值为9,因此所有计时器基本上都在设置arr[9]。

    这是不正确的,不起作用。您将直接调用函数,而不是在100毫秒后。您将向它传递一个参数,但它将被丢弃。然后从外部范围中获取
    索引
    ,这很好,因为它是同步执行的。100毫秒后,什么也没有发生。如果你在firefow草稿行中剪切粘贴代码,它将显示“我是约翰”,这是第一个问题。我只是想帮助解决这个错误。如果我有两个参数(我不应该传递)而不是索引呢?例如:
    函数(结果、状态)
    。那么我们如何使用bind呢?基本上就像
    Function.prototype.call
    一样使用它。所以您需要执行
    fn.bind(context、firstParam、secondParam、thirdParam)
    等等。
    this.createAssignmentCallback = function (index) {
        var self = this;
        return function () {
             self.arr[index] = 'I am John!';
        };
    };
    
    this.setMember = function() {
        var self = this;
        var index;
    
        for(; this.counter < 10; this.counter++){
            index = this.counter;
            setTimeout(this.createAssignmentCallback(index), 100);
        }
    };  
    
    this.setMember = function() {
        for(; this.counter < 10; this.counter++){
            setTimeout(function(i){
                this.arr[i] = 'I am John!';
            }.bind(this, this.counter), 100);
        }
    };
    
    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);