如何在javascript中从子类调用父方法?

Yem*_*lat 134 javascript oop methods parent

我花了最后几个小时试图找到问题的解决方案,但似乎没有希望.

基本上我需要知道如何从子类调用父方法.到目前为止,我尝试过的所有内容都会导致无法正常工作或覆盖父方法.

我使用以下代码在javascript中设置OOP:

// SET UP OOP
// surrogate constructor (empty function)
function surrogateCtor() {}

function extend(base, sub) {
    // copy the prototype from the base to setup inheritance
    surrogateCtor.prototype = base.prototype;
    sub.prototype = new surrogateCtor();
    sub.prototype.constructor = sub;
}

// parent class
function ParentObject(name) {
    this.name = name;
}
// parent's methods
ParentObject.prototype = {
    myMethod: function(arg) {
        this.name = arg;
    }
}

// child
function ChildObject(name) {
    // call the parent's constructor
    ParentObject.call(this, name);
    this.myMethod = function(arg) {
        // HOW DO I CALL THE PARENT METHOD HERE?
        // do stuff
    }
}

// setup the prototype chain
extend(ParentObject, ChildObject);
Run Code Online (Sandbox Code Playgroud)

我需要先调用父方法,然后在子类中添加更多东西.

在大多数OOP语言中,就像调用一样简单parent.myMethod() 但我真的无法掌握它在javascript中的完成情况.

非常感谢任何帮助,谢谢!

Yem*_*lat 178

这是它的完成方式: ParentClass.prototype.myMethod();

或者,如果要在当前实例的上下文中调用它,可以执行以下操作: ParentClass.prototype.myMethod.call(this)

从带有参数的子类调用父方法也是如此: ParentClass.prototype.myMethod.call(this, arg1, arg2, ..)*提示:使用apply()而不是call()将参数作为数组传递.

  • 如果要在当前实例的上下文中调用它,则必须执行`ParentClass.prototype.myMethod.apply()或`ParentClass.prototype.myMethod.call()`,就像使用构造函数一样. (7认同)
  • 只是添加一个,如果你想用参数调用,它们进入apply或call函数(`ParentClass.prototype.myMethod.call(this,arg1,arg2,arg3 ...);`) (3认同)
  • 我当前正在使用this.myFun = function(){}声明一个对象方法,因此调用ParentClass.prototype.myFun.call(...)无法正常工作,因此我必须使用CurrentClass.prototype.myFun.call( ...)。JS是...废话,我们应该使用真正的OOP。 (2认同)

Dmy*_*vid 125

ES6样式允许您使用新功能,例如super关键字.super关键字它是关于父类上下文的,当您使用ES6类语法时.作为一个非常简单的例子,结帐:

class Foo {
    static classMethod() {
        return 'hello';
    }
}

class Bar extends Foo {
    static classMethod() {
        return super.classMethod() + ', too';
    }
}
Bar.classMethod(); // 'hello, too'
Run Code Online (Sandbox Code Playgroud)

此外,您可以使用super调用父构造函数:

class Foo {}

class Bar extends Foo {
    constructor(num) {
        let tmp = num * 2; // OK
        this.num = num; // ReferenceError
        super();
        this.num = num; // OK
    }
}
Run Code Online (Sandbox Code Playgroud)

当然,您可以使用它来访问父类属性super.prop.所以,使用ES6并感到高兴.

  • @ fsinisi90我相信,问题不是关于父类的方法,而是关于父类的实例方法,这些方法在ES6中不能用super关键字调用. (7认同)
  • 为什么这个答案没有更多的赞成?:) (3认同)
  • 必须在子类构造函数中调用super()。 (2认同)
  • @GianlucaCasati:你只能在静态方法中使用`super()`;看起来你在构造函数中使用了它。 (2认同)

Red*_*edu 7

为了做到这一点,您不受ClassES6 抽象的限制。可以通过__proto__属性访问父构造函数的原型方法(我很确定会有其他 JS 编码员抱怨它已贬值),该属性已贬值,但同时发现它实际上是满足子类需求的重要工具(尤其是对于 Array 子分类需要)。因此,虽然该__proto__属性在我知道的所有主要 JS 引擎中仍然可用,但 ES6Object.getPrototypeOf()在其之上引入了该功能。抽象中的super()工具Class是它的语法糖。

因此,如果您无权访问父构造函数的名称并且不想使用Class抽象,您仍然可以执行以下操作;

function ChildObject(name) {
    // call the parent's constructor
    ParentObject.call(this, name);
    this.myMethod = function(arg) {
    //this.__proto__.__proto__.myMethod.call(this,arg);
    Object.getPrototypeOf(Object.getPrototypeOf(this)).myMethod.call(this,arg);
    }
}
Run Code Online (Sandbox Code Playgroud)


Cap*_*Wiz 5

这是使用 JavaScript 的原型链让子对象访问父属性和方法的好方法,并且它与 Internet Explorer 兼容。JavaScript 在原型链中搜索方法,我们希望子代的原型链如下所示:

子实例-> 子的原型(带子方法)-> 父的原型(带父方法)-> 对象原型-> null

子方法也可以调用隐藏的父方法,如下面的三个星号 *** 所示。

就是这样:

//Parent constructor
function ParentConstructor(firstName){
    //add parent properties:
    this.parentProperty = firstName;
}

//add 2 Parent methods:
ParentConstructor.prototype.parentMethod = function(argument){
    console.log(
            "Parent says: argument=" + argument +
            ", parentProperty=" + this.parentProperty +
            ", childProperty=" + this.childProperty
    );
};

ParentConstructor.prototype.commonMethod = function(argument){
    console.log("Hello from Parent! argument=" + argument);
};

//Child constructor    
function ChildConstructor(firstName, lastName){
    //first add parent's properties
    ParentConstructor.call(this, firstName);

    //now add child's properties:
    this.childProperty = lastName;
}

//insert Parent's methods into Child's prototype chain
var rCopyParentProto = Object.create(ParentConstructor.prototype);
rCopyParentProto.constructor = ChildConstructor;
ChildConstructor.prototype = rCopyParentProto;

//add 2 Child methods:
ChildConstructor.prototype.childMethod = function(argument){
    console.log(
            "Child says: argument=" + argument +
            ", parentProperty=" + this.parentProperty +
            ", childProperty=" + this.childProperty
    );
};

ChildConstructor.prototype.commonMethod = function(argument){
    console.log("Hello from Child! argument=" + argument);

    // *** call Parent's version of common method
    ParentConstructor.prototype.commonMethod(argument);
};

//create an instance of Child
var child_1 = new ChildConstructor('Albert', 'Einstein');

//call Child method
child_1.childMethod('do child method');

//call Parent method
child_1.parentMethod('do parent method');

//call common method
child_1.commonMethod('do common method');
Run Code Online (Sandbox Code Playgroud)