JS原型类并非所有属性都可访问

JS prototype class not all properties are accessible

本文关键字:属性 访问 原型 JS      更新时间:2023-09-26

我定义了一个原型类,它几乎没有属性和方法,由于某些原因,在某些情况下(主要是涉及回调时)我无法访问所有属性。

这是我的代码(删除了一些行以使其更清晰)

var Lobby = function (preloader, serverConn) {
  // Hold a reference to EventBus
  this.serverConn = serverConn;
  this.preloader = preloader;
  this.session_id = null;
  this.scheduleItemService = new ScheduledItemService(this.preloader);
  // Instantiate lobby stage
  this.stage = new createjs.Stage("lobbyCanvas");
};
Lobby.prototype._renderLobbyImages = function(stage, scheduleItemService) {
   // at this point, 'stage' and 'scheduleItemService' are valid!
  ..
  // onScheduledItemClick callback function
  this.scheduleItemService.render(stage, this._onScheduledItemClick);
}
Lobby.prototype._onScheduledItemClick = function(event) {
  (function(inst) {
  inst.serverConn.asyncSend(
    'game.lobby',
    { 'action' : 'claim_scheduled_item',
        'session_id' : inst.session_id, **//Here, 'inst.session_id' is DEFINED!**
    },
    function (error, reply) {
      **// Here, both 'stage' and 'scheduleItemService' are UNDEFINED! WHY?!?!**
      inst.scheduleItemService.startCountdown(inst.stage);
    }
   });
  })(this);
}
ScheduledItemService.prototype.render = function(stage, onScheduledItemClick) {
  var scheduled_item = new createjs.Bitmap(preloader.getResult("scheduled_item_img"));
..
..
  scheduled_item.addEventListener('click', onScheduledItemClick);
..
}

为什么this.session_id在"this"中定义,而"stage"answers"scheduleItemService"未定义??这3个是大堂类的属性。。。

我尝试在"this"指针中浏览,但确实找不到"stage"answers"scheduleItemService"。

我错过了什么,对吧?

谢谢:-)

此处的scheduleItemService变量超出范围

function (error, reply) {
      scheduleItemService.startCountdown(stage);
}

问题是,即使你没有使用Promises,这个代码仍然会失败。如果你想将renderLobbyImagesonScheduledItemClick定义为原型方法,你必须编写

Lobby.prototype.renderLobbyImages = function(){
    // this refers to a Lobby instance
    this.scheduleItemService.render(stage, this.onScheduledItemClick);
}
Lobby.prototype.onScheduledItemClick = function(){
    // this refers to a lobby instance
}

您还必须在onScheduledItemClick中使用use this关键字。

然后,在您定义的promise回调中,"this"关键字不会指向实例。这就是您的代码出现错误的原因。在这个回调中,this发生了变化。

为了解决这个问题,在回调之前,将一个临时变量存储到"this,在这里我将其命名为scope"。您可以像使用this一样使用此scope

Lobby.prototype.onScheduledItemClick = function(event) {
  // this refers to a lobby instance
  var scope = this;
  this.serverConn.asyncSend(
    'game.lobby',
    { 
        'action'     : 'claim_scheduled_item',
        'session_id' : scope.session_id.bind(scope), // Here scope instead of this. But you could use this as not inside callback. I used scope just for consistency
    },
    function (error, reply) {
      // this does NOT refer to a lobby instance. You must use scope
      scope.scheduleItemService.startCountdown(stage);
    }
});

编辑1

在您的代码编辑之后,我仍然可以看到一些错误。

我看到在您的Lobby.prototype._onScheduledItemClick中,您使用的是(inst)变量this.serverConn.asyncSend,它应该是inst.serverConn.asyncSen

--

编辑2

代码的另一个问题是回调。该范围未传递。您必须将回调与作用域"绑定"。这是使用函数.bind();

所以现在,你的线路看起来像:

this.scheduleItemService.render(stage, this._onScheduledItemClick.bind(this));

这样,当调用回调时,"this"变量将具有您在bind中传递的参数的值。

首先,您没有在您的东西前面加上this。与其他一些语言不同,this在JavaScript中不是可选的。

当您输入一个新的函数调用时,this将被重新定义。您将需要保存对它的引用。

CCD_ 21被定义为被调用函数的父函数。因此,每次调用函数时,它都会发生变化。以下是人们经常做的事情:

Something.prototype.foo = function() {
    var self = this;
    doSomething(function() {
        // now this has changed, but self still references the original this
   });
};