0

我正在使用 CraftyJS 编写一个小游戏。这是我想写的:

Crafty.scene('MainMap', function() {

    this.player = Crafty.e('Player');       
    this.player.move(5, 5);
    this.game_objects = [this.player];

    isOccupied: function(x, y) {
        for (var i = 0; i < this.game_objects.length; i++) {
            // ...
        }
    }

    if (!this.isOccupied(5, 5)) { ... }

    // ...
}

不幸的是,这并没有按预期工作。它不是匿名对象,而是一个函数。我必须使用不同的语法,并传入我的对象,如下所示:

function isOccupied(x, y, game_objects) { ... }
// Same place as previous call to isOccupied
if (!isOccupied(x, y, this.gameObjects) { ... }

我很清楚为什么我必须将它声明为function isOccupied而不是isOccupied: function(因为它在函数内部,而不是对象中),但我不清楚范围this是什么。它不会传递给函数。

是否有可能以某种方式将对象保持在某个非全局范围内,而不需要将它们传递给isOccupied?

4

3 回答 3

2

您可以将父范围分配给另一个变量,因此它将在您的闭包中可用。像这样...

Crafty.scene('MainMap', function() {
    var self = this;
    this.player = Crafty.e('Player');       
    this.player.move(5, 5);
    this.game_objects = [this.player];

    function isOccupied (x, y) {
        for (var i = 0; i < self.game_objects.length; i++) {
        // ...
        }
    }
}
于 2014-01-11T14:38:05.490 回答
2

您的 Crafty 场景中有语法错误。

这部分的冒号不应该在那里。在 JavaScript 中,冒号仅用于对象。

// Wrong
isOccupied: function(x, y) {
     for (var i = 0; i < this.game_objects.length; i++) {
            // ...
     }
}

// Right
function isOccupied(x, y) {
   // ...
}

在您的函数中,this指的是全局对象 ( window)。

编辑:要解决此问题,请使用Function.prototype.bind,如下所示:

function isOccupied(x, y) {
   // ...
}.bind(this);
于 2014-01-11T14:39:42.360 回答
0

经过更多研究,这似乎是关键字的一个众所周知的问题。this它将在 ECMAscript 5 中修复。

总而言之:this当您有多个嵌套级别时,关键字会变得混乱:

obj = {
  speak: function() {
    alert(this); // obj
    inner = function() {
        alert("inner: " + this); // window
    };
  }
};

解决方法是使用作用域链,通过将变量分配给this

obj = {
  speak: function() {
    alert(this); // obj
    var that = this;
    inner = function() {
        alert("inner: " + that); // obj instead of window
    };
  }
};

对我来说不幸的是,CraftJS 让我在一个函数而不是一个对象中。要声明子函数,我仍然必须将其指定为function isOccupied

Crafty.scene('MainMap', function() {
    self = this; // new
    this.player = Crafty.e('Player');       
    this.player.move(5, 5);
    this.game_objects = [this.player];

    function isOccupied(x, y) { // game_objects no longer passed in
        for (var i = 0; i < self.game_objects.length; i++) { // uses self
            // ...
        }
    }

    if (!this.isOccupied(5, 5)) { ... }

    // ...
}
于 2014-01-11T17:22:00.383 回答