“这个”成为“窗口”JavaScript

时间:2015-07-06 13:50:05

标签: javascript window this

我正在尝试开发一个小游戏,我有以下问题:我有一个伪类“Cannon”,每个Cannon都有一个数组,用于存储它应该守卫的区域和一个存储“入侵者”的数组进入其中一个守卫区域。我创建了下一个函数作为Cannon原型的一部分:

Cannon.prototype.checkIntruderLeftGuardedAreas = function(){
    debugger;
    this.intruders = this.intruders.filter(function(intruder){
        for(var i = 0, l = this.guardedAreas.length; i < l; i ++)
        {
            if(intruder.inInsideGuardedArea(this.guardedAreas[i]))
            {
                return true;
            }
        }
        return false;
    });
}

在第三行,我试图过滤那些已经离开守卫区域的入侵者,但是“这个”引用了“窗口”而不是调用该函数的Cannon对象。

我也试过这段代码:

var intrudersArray = [];
    for(var i = 0, l = this.guardedAreas.length; i < l; i ++)
        {
            for(var j = 0, k = this.intruders.length; j < k; j++)
            {
               if(this.intruders[j].inInsideGuardedArea(this.guardedAreas[i]))
               {
                   intrudersArray.push(this.intruders[j]);
               }
            }

        }

        this.intruders = intrudersArray;

根据我的逻辑,这与前一段代码做了同样的事情:过滤入侵者数组。问题是在“if”开始的第6行,突然“this”引用“window”!在达到if条件之前,“this”引用调用该函数的Cannon对象。

2 个答案:

答案 0 :(得分:2)

是的,范围可能会变得棘手,您可以尝试以下方法:

Cannon.prototype.checkIntruderLeftGuardedAreas = function(){
    var self = this;

    self.intruders = self.intruders.filter(function(intruder){
        for(var i = 0, l = self.guardedAreas.length; i < l; i ++)
        {
            if(intruder.inInsideGuardedArea(self.guardedAreas[i]))
            {
                return true;
            }
        }
        return false;
    });
}

注意第var self = this;行。它的目的是保存对你的cannon实例的引用,以便在嵌套回调中使用(注意this self filter this内部的self},以避免范围问题,这种情况很常见在jQuery代码中。

这种做法确保你引用你的大炮而不需要跟踪{{1}},{{1}}正在发生的事情,乍看之下这是显而易见的。

答案 1 :(得分:0)

当您调用checkIntruderLeftGuardedAreas时,请绑定&#34;此&#34;来自被叫者的对象。

obj.checkIntruderLeftGuardedAreas.bind(this)(arg1, arg2, ..., argn);

在JavaScript中,这是一个上下文,而不是当前的类。

示例:定义一个输出&#34;此&#34;

的函数
function lol(){console.log(this);}

现在调用该函数

洛尔();

你得到了窗口。

此外,定义一个函数,并在对象中调用它:

var obj = {  abc: function(){lol(); }}

然后

obj.abc();

仍会让你开窗 你需要

var obj = {  abc: function(){lol.bind(this)(); }}

当您调用函数

时,此上下文将更改为obj
obj.abc();

您可能必须这样做:

Cannon.prototype.checkIntruderLeftGuardedAreas = function(){
    debugger;
    this.intruders = this.intruders.filter(function(intruder){
        for(var i = 0, l = this.guardedAreas.length; i < l; i ++)
        {
            if(intruder.inInsideGuardedArea(this.guardedAreas[i]))
            {
                return true;
            }
        }
        return false;
    }).bind(this);
}

注意&#34; bind&#34;在倒数第二行。