setInterval,再次

时间:2014-12-19 16:57:36

标签: javascript scope setinterval

我对setInterval有一个问题,我无法弄清楚。

我知道" (...)当从对象内部调用setInterval或timeout时,范围存在问题,但仍然无法绕过它。

我试图把我的东西放在一个匿名函数中,它不会工作。

这基本上是我的问题,简化为骨干:

function Scenario(){
    var ships = [];
    this.ini = function(){
        for (var i = 0; i < ships.length; i++){
            timeoutID1 = setTimeout(ships[i].ding, 1000);
            timeoutID2 = setTimeout(ships[i].bing, 1000);
        }
    }
    this.setShips = function(){
        var ship = new Ship("ship");
        ships.push(ship);    
    }        

    function Ship(name){
        this.name = name;
        this.ding = function(){
            intervalID1 = setInterval(function(){
                console.log("ding");
            }, 500)      
        }
        this.bing = function(){
            var _this = this;
            intervalID2 = setInterval(function(){
                console.log(_this.name);
            }, 500)      
        }
    }
    this.setShips();
}


var scenario = new Scenario();
scenario.ini();

http://jsfiddle.net/ancientsion/xkwsn7xd/

基本上,console.log(&#34; ding&#34;)有效, console.log(_this.name)不是。

为什么?

5 个答案:

答案 0 :(得分:2)

这是你的问题简化为裸骨:

var ship = {
    name: 'Sheep',
    ding: function() {
        console.log(this.name);
    }
}

setTimeout(ship.ding, 1000); // doesn't work correctly

可能有助于看到另一个例子来理解为什么上述方法不起作用:

var ding = ship.ding;
ding(); // doesn't work either

在JavaScript中this取决于您如何调用您的函数。 ship.ding()会将this设置为sheep对象。仅ding()次调用会将this设置为window对象。

您可以使用.bind()方法将函数绑定到所需的对象。 (Function.prototype.bind()

var ding = ship.ding.bind(ship);
ding(); // works

ding现在永久绑定到sheep对象。您可以使用与setTimeout完全相同的方法:

setTimeout(ship.ding.bind(ship), 1000);

答案 1 :(得分:0)

您应该在_this函数中定义值Ship

function Ship(name){
    this.name = name;
    this.ding = function(){
        intervalID1 = setInterval(function(){
            console.log("ding");
        }, 500)      
    }
    var _this = this;
    this.bing = function(){
        intervalID2 = setInterval(function(){
            console.log(_this.name);
        }, 500)      
    }
}

答案 2 :(得分:0)

从bing函数中提升_this。

你应该

_this = this,
this.bing = function() {
            intervalID2 = setInterval(function(){
                console.log(_this.name);
            }, 500)   
}  

Javascript是必不可少的,因此您需要仔细遵循执行路径。在函数Ship中,这指向Ship对象,在函数bing中,它指向全局范围(窗口)。您需要保存对此的引用,以便您可以在这些类型的函数中引用它。

答案 3 :(得分:0)

setTimeout()到处调用你的方法时,它只能看到函数,而不是调用上下文(即绑定它的对象);很像这样:

var bing = ships[i].bing;

bing(); // inside bing(), this == window

基本上,您需要为setTimeout()提供预先接线的方法调用:

var bound_bing = ships[i].bing.bind(ships[i]);
timeoutID2 = setTimeout(bound_bing, 1000);

&#34;魔法&#34;与.bind()一起发生,因为它返回一个新功能,可以正确设置this

答案 4 :(得分:0)

你把ships[i].bing放在setTimeout中,结果是bing的调用者不是ship [i]而是全局的,所以_this实际指向全局。