【问题标题】:Weird behaviour when trying to do prototype inheritance尝试进行原型继承时的奇怪行为
【发布时间】:2018-09-08 23:41:33
【问题描述】:

我理解原型继承,(即:如果属性未在当前对象上定义,则遍历原型链,直到找到属性或函数,然后执行或返回 null)。

问题是我在应该定义属性时得到“未定义”。此属性称为 _context

以下是 Chrome 检查器控制台的输出。它清楚地表明 _context 是在 YouAreConnected 的原型上定义的。 (靠近底部)

但是我的 Jasmine 测试失败了,因为它说 _context 没有在实现中定义。

下面是实现。

define(['voice/states-new/State'],
function(State){

  var YouAreConnected = function YouAreConnected(context){

    Object.setPrototypeOf(this,new State());

    if(!context){
        throw Error('context must be set.');
    }
    else{
        this.__proto__._context = context;
    }

    /**
     * Initializes this state.
     *
     * pre:
     * - _context must be set with a socket connection
     *   which is 'connected'.
     *
     * post:
     * - Any initialization involving the server is
     *   executed.
     */
    this.init = function(){

      console.log(this);   // this produced the chrome console output.

      this._context.socket.emit('createRoom',_context.userId);
    }
  }

  return YouAreConnected;

});

下面是 Jasmine 测试用例。

  it('emits a "createRoom" event to the server upon creation', ()=>{
      var _context = TestHelper.mockContext;
      var state = new YouAreConnected(_context);
      spyOn(_context.socket,'emit');
      state.init();
      expect(_context.socket.emit).toHaveBeenCalled();
  })

更新 1 似乎当我将字符串而不是对象传递给 YouAreConnected 构造函数时,_context 不再是未定义的。

失败了

it('emits a "createRoom" event to the server upon creation', ()=>{
      //var _context = TestHelper.mockContext;
      var state = new YouAreConnected({});  // object passed
      spyOn(_context.socket,'emit');
      state.init();
      expect(_context.socket.emit).toHaveBeenCalled();
  })

这可行(_context 不再未定义)

it('emits a "createRoom" event to the server upon creation', ()=>{
      //var _context = TestHelper.mockContext;
      var state = new YouAreConnected("mock");  // string passed
      spyOn(_context.socket,'emit');
      state.init();
      expect(_context.socket.emit).toHaveBeenCalled();
  })

更新 2

有效(此处不显示 _context undefined)。

  it('emits a "createRoom" event to the server upon creation', ()=>{

      var _context = {

      }
      var state = new YouAreConnected(_context);
      state.init();
  })

但是,当我将 'socket' 属性添加到模拟对象时,它再次显示 _context 未定义。我不明白为什么。

  it('emits a "createRoom" event to the server upon creation', () => {
      var _context = {
        socket:{

        }
      }
      var state = new YouAreConnected(_context);
      state.init();
  })

【问题讨论】:

  • 永远不要使用 __proto__,使用 setprototypeof ,developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
  • 我提炼了这个问题。 _context 属性已在原型上定义,但仍未找到。
  • 你不需要把 _context 放在原型上,你为什么首先要这样做?只需让它成为 YouAreConnected 的属性,只需编写 this._context = context
  • 你是正确的mpm。但是,由于原型继承,它应该以任何一种方式工作。我确实尝试了您的建议,但发生了同样的失败。

标签: javascript inheritance design-patterns


【解决方案1】:

你在打电话:

this._context.socket.emit('createRoom',_context.userId),

但是 emit 中的 _context 参数不是局部变量,所以需要使用:

this._context.userId

对于那个论点。即:

this._context.socket.emit('createRoom',this._context.userId),

此外,您从未在 _context 上设置 userId,但这是一个不同的问题。

【讨论】:

    猜你喜欢
    • 2014-06-30
    • 1970-01-01
    • 2012-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多