调用prototype的重写方法,然后调用下一个原型的重写方法错误

时间:2012-05-14 18:24:10

标签: javascript prototypal-inheritance

我正在尝试覆盖对象的方法,但仍使用Object.getPrototypeOf()调用原型的原始方法。这在第一次工作得很好,但是如果方法被多次覆盖则存在问题。

此代码导致堆栈溢出:

A =
{
   blurg: function()
   {
      puts('hey there')
   }
}

B = (function buildB(){
   var obj = Object.create(A)

   obj.blurg = function()
   {
      Object.getPrototypeOf(this).blurg.apply(this, arguments)

      puts('hai!!!!')
   }

   return obj
})()

b = (function buildb(){
   var obj = Object.create(B)

   obj.blurg = function()
   {
      Object.getPrototypeOf(this).blurg.apply(this, arguments)

      puts('bye bye')
   }

   return obj
})()


b.blurg()

jsFiddle

问题是我想用当前对象调用原型的方法this。当该方法做同样的事情时,这会导致问题。

我是以错误的方式来做这件事的吗?有没有办法可以创建一个辅助函数来确保正确的原型被拉起来?我有点不知所措。

1 个答案:

答案 0 :(得分:3)

问题在于,在JavaScript中,this本质上总是引用原型链中的自底向下对象实例,因此当您覆盖上述层次结构中的方法时,this.prototype.someMethod()指的是对象实例的确切基类,当您最多有两个层次结构时,它似乎不是问题,但是当您定义三个层次结构或更多层次时,递归是不可避免的!这是如何:

A: grand super class
B: super class - inherits from A (B.prototype = A)
C: class - inherits from B (C.prototype = B)

a: instance of A (defines someMethod)
b: instance of B (defines someMethod, calls A.someMethod through Object.getPrototypeOf(this))
c: instance of C (defines someMethod, calls B.someMethod through Object.getPrototypeOf(this))

调用b.someMethod时,它可以成功调用A的someMethod(Object.getPrototypeOf(this)在被b调用时返回A)

但是,当c.someMethod被调用时,它首先调用b.someMethod,然后调用b.someMethod,因为Object.getPrototypeOf(this)在被c调用时总是返回B!这里是堆栈溢出的地方。

要解决此问题,请在定义新的子类时尝试存储基类引用,避免在调用超类方法时使用this

A =
{
    blurg: function () {
        console.log('hey there')
    }
};

B = (function buildB() {
    var obj = Object.create(A);
    var base = Object.getPrototypeOf(obj);

    obj.blurg = function () {
        base.blurg.apply(this, arguments);
        console.log('hai!!!!')
    }

    return obj
})();

C = (function buildb() {
    var obj = Object.create(B);
    var base = Object.getPrototypeOf(obj);

    obj.blurg = function () {
        base.blurg.apply(this, arguments);
        console.log('bye bye');
    }

    return obj
})();

C.blurg();