简体   繁体   English

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

[英]JS prototype class not all properties are accessible

I have defined a prototype class with few properties and methods and for some reason I cannot access all the properties in some cases (mainly when callbacks are involved). 我已经定义了一个原型类,其属性和方法很少,由于某些原因,在某些情况下(主要是涉及回调时),我无法访问所有属性。

Here is my code (removed some lines to make it clearer) 这是我的代码(删除了一些行使其更加清晰)

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);
..
}

Why this.session_id is defined in 'this' while 'stage' and 'scheduleItemService' are not defined?? 为什么未在“ stage”和“ scheduleItemService”中定义“ this”中定义this.session_id? these 3 are properties of Lobby class... 这3个是大堂类的属性...

I tried browsing in 'this' pointer and I really couldn't find 'stage' nor 'scheduleItemService'. 我尝试浏览“ this”指针,但实际上找不到“ stage”或“ scheduleItemService”。

I'm missing something, right? 我想念什么,对不对?

Thank you :-) 谢谢 :-)

Your scheduleItemService variable is out of scope here 您的scheduleItemService变量超出了此处的范围

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

The thing is even if you did not use Promises, this code would still fail. 问题是,即使您没有使用Promises,此代码仍然会失败。 If you want to define the renderLobbyImages and onScheduledItemClick as prototype methods, you'd have to write 如果您想将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
}

You must also use the use this keyword in the onScheduledItemClick . 您还必须在onScheduledItemClick使用use this关键字。

Then, inside the promise callback you defined, the " this " keyword does not point back to the instance. 然后,在您定义的Promise回调中,“ this ”关键字不指向实例。 That's why you are getting errors with your code. 这就是为什么您的代码出错。 Inside this callback, the this changes. 在此回调内部, this更改。

To fix this, before the callback, store a temporary variable to the " this , here I named it scope ". 为了解决这个问题,在回调之前,将一个临时变量存储到“ this ,在这里我将其命名为scope ”。 You can use this scope the same way you use this . 你可以使用这个scope ,你用同样的方法this

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);
    }
});

Edit 1 编辑1

After your code edit, I can still see some errors. 编辑完代码后,我仍然可以看到一些错误。

I see that in your Lobby.prototype._onScheduledItemClick , you are using a (inst) variable, this.serverConn.asyncSend , it should be inst.serverConn.asyncSen 我看到在Lobby.prototype._onScheduledItemClick ,您使用的是一个(inst)变量this.serverConn.asyncSend ,它应该是inst.serverConn.asyncSen

-- -

Edit 2 编辑2

Another problem with your code is the callback. 您的代码的另一个问题是回调。 The scope is not passed along. 范围未传递。 You have to "bind" your callback with a scope. 您必须将“回调”与作用域“绑定”。 This is used using function.bind() ; 使用function.bind() ;

So now, your line looks like : 所以现在,您的行看起来像:

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

This will make it so that when your callback is called, the " this " variable will have the value of the argument you pass in bind . 这样可以确保在调用回调时,“ this ”变量将具有您在bind传递的参数值。

Firstly, you aren't prefixing your things with this . 首先,您不会在this添加前缀。 Unlike some other languages, this is not optional in JavaScript. 与其他一些语言不同, this在JavaScript中不是可选的。

When you enter a new function call, this is redefined. 当你进入一个新的函数调用, this被重新定义。 You'll want to save a reference to it. 您需要保存对其的引用。

this is defined as the parent of the called function. this被定义为被调用函数的父级。 Therefore it changes each time a function is called. 因此,每次调用函数时它都会改变。 Here's what people often do: 人们经常这样做:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM