在JavaScript类中调用父方法,但仍然可以访问对象实例中的原型方法?

时间:2014-10-03 11:57:14

标签: javascript class oop extending

是否可以在JavaScript类中调用父方法,但仍然可以访问父类和子类的原型方法。这是代码示例:

var Base = function() {

  this.baseMethod = function(){
    return 'baseMethod';
  };

  this.baseInitMethod = function() {
    return 'baseInitMethod';
  }
}


Base.prototype.basePrototypeMethod = function() {
  return "basePrototypeMethod";
};


var Specific = function() {

  Base.call(this);

  this.baseInitMethod = function() {
    // call baseInitMethod from Base class
  }

  this.specificMethod = function(){
    return 'specificMethod';
  }

  this.specificInitMethod = function() {

    return this.basePrototypeMethod();
  }
}


Specific.prototype.specificPrototypeMethod = function() {
  return 'specificPrototypeMethod' + '-' + this.baseInitMethod();
}


for(var p in Base.prototype) {
   Specific.prototype[p] = Base.prototype[p]
}


var s = new Specific();


console.log(s.baseMethod());

console.log(s.baseInitMethod());

console.log(s.basePrototypeMethod());

console.log(s.specificMethod());

console.log(s.specificInitMethod());

console.log(s.specificPrototypeMethod());

我想从Base类中的baseInitMethod方法中调用baseInitMethod,但是所有来自上面的函数调用仍然有效。这可能吗?

5 个答案:

答案 0 :(得分:1)

以下是您需要做的事情:

var Base = function () {
};
Base.prototype.baseMethod = function () {
    return 'baseMethod';
};
Base.prototype.baseInitMethod = function () {
    return 'baseInitMethod';
};
Base.prototype.basePrototypeMethod = function () {
    return "basePrototypeMethod";
};


var Specific = function () {
    Base.apply(this, arguments);
};
Specific.prototype.baseInitMethod = function () {
    Base.prototype.baseInitMethod.apply(this,arguments);
};

Specific.prototype.specificMethod = function () {
    return 'specificMethod';
};

Specific.prototype.specificInitMethod = function () {
    var basePrototypeMethodCallResult = Base.prototype.basePrototypeMethod.apply(this,arguments);

};

答案 1 :(得分:1)

您的Specific.prototype对象应Base.prototype对象继承。目前,您正在使用以下代码将所有属性复制到对象:

for(var p in Base.prototype) {
   Specific.prototype[p] = Base.prototype[p]
}

但您实际上应该使用Object.create来建立真正的原型链

Specific.prototype = Object.create(Base.prototype);

Specific.prototype.specificPrototypeMethod = function() {
  return 'specificPrototypeMethod' + '-' + this.baseInitMethod();
}

  

我想从Base类中的baseInitMethod中调用baseInitMethod

是。在Specific构造函数中,首先需要获取Base baseInitMethod实例方法,然后才覆盖实例的属性:

function Specific() {
    Base.call(this);

    var parentInitMethod = this.baseInitMethod;
    this.baseInitMethod = function() {
        // call baseInitMethod from Base class:
        parentInitMethod.call(this /*, arguments…*/); 
    }

    …
}
  

以便上面的所有函数调用仍然有效。

我不确定你到底是什么意思。 specificPrototypeMethod将始终调用当前实例的baseInitMethodSpecific覆盖Base,而不是{{1}}中定义的原始实例。

答案 2 :(得分:0)

你用baseInitMethod的定义覆盖了BaseSpecific的{​​{1}},那你为什么要调用Base版本呢?如果您只是删除函数的覆盖,则应调用Base定义:

Specific

答案 3 :(得分:0)

有人可能会争辩说"为什么总是试图模仿古典'使用callapply而不是采用原型委派模式的行为和烦恼呢?"

以下是我要编码的内容:

var Base = {

    baseVariable1: "baseValue1",

    baseVariable2: "baseValue2",

    baseMethod: function () {
        return 'baseMethod';
    },

    baseInitMethod: function () {
        return 'baseInitMethod';
    }
}

var Specific = Object.create(Base);

Specific.variable1 = "value1";

Specific.variable2 = "value2";

Specific.specificInitMethod = function () {
    return 'specificInitMethod' + '-' + this.baseInitMethod();
}

Specific.specificMethod = function () {
    return 'specificMethod' + '-' + this.baseInitMethod();
}

var s = Object.create(Specific);

console.log(s.baseInitMethod());

console.log(s.baseVariable1);

console.log(s.baseVariable2);

console.log(s.variable1);

console.log(s.variable2);

console.log(s.baseMethod());

console.log(s.specificInitMethod());

console.log(s.specificMethod());

答案 4 :(得分:0)

class Parentable {
  get parent() {
    return this.__proto__.__proto__;
  }
} 
class A extends Parentable { 
  say() { 
    console.log('Hello from A'); 
  } 
}
class B extends A {
  say() {
   console.log('Im not A, I am B! But A send you a message:');
   this.parent.say();
  }
}
(new B()).say();