【问题标题】:Scope of "this" in inner function (CraftyJS scene)内部函数中“this”的范围(CraftyJS 场景)
【发布时间】:2014-04-27 19:18:03
【问题描述】:

我正在使用 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

【问题讨论】:

    标签: javascript craftyjs


    【解决方案1】:

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

    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++) {
            // ...
            }
        }
    }
    

    【讨论】:

    • this.isOccupied = function...if (isOccupied... 两者都是错误。
    • 我收到isOccupied is not a function 的错误。我必须将其声明为function isOccupied。尽管您提供了解决方法,但它并没有解释范围。
    【解决方案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);
    

    【讨论】:

    • 您提供了解释,但没有解决方案。
    • 我的声誉分数太低,无法发表评论
    • 哦,对不起。不过,这是我想知道的一部分:)
    【解决方案3】:

    经过更多研究,这似乎是带有this 关键字的well-known issue。它将在 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)) { ... }
    
        // ...
    }
    

    【讨论】:

      猜你喜欢
      • 2011-07-07
      • 1970-01-01
      • 2021-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-25
      • 2016-09-30
      相关资源
      最近更新 更多