我花了几个小时试图找到解决问题的办法,但似乎毫无希望。

基本上,我需要知道如何从子类调用父方法。 到目前为止,我所尝试的所有东西都以无效或重写父方法而告终。

我使用下面的代码在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);

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

在大多数OOP语言中,调用parent.myMethod()就可以了 但我真的不能理解它是如何在javascript中完成的。

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


当前回答

ES6风格允许您使用新功能,如超级关键字。super关键字,当你使用ES6类语法时,它都是关于父类上下文的。作为一个非常简单的例子,签出:

记住:我们不能通过实例方法中的super关键字调用父静态方法。调用方法也应该是静态的。

通过实例方法调用静态方法- TypeError ! 类Foo { static classMethod() { 返回“你好”; } } 类Bar扩展Foo { classMethod () { return super.classMethod() + ', too'; } } console.log (Bar.classMethod ());// 'hello' -调用继承的静态方法 console.log(())(新酒吧.classMethod ());// 'Uncaught TypeError' -调用一个实例方法

通过super调用静态方法-这是有效的!

类Foo { static classMethod() { 返回“你好”; } } 类Bar扩展Foo { static classMethod() { return super.classMethod() + ', too'; } } console.log (Bar.classMethod ());// 'hello, too'

现在,超级上下文基于调用而改变——瞧!

类Foo { static classMethod() { 返回'hello I am static only'; } classMethod () { 返回'hello there I am an instance '; } } 类Bar扩展Foo { classMethod () { return super.classMethod() + ', too'; } } console.log(())(新酒吧.classMethod ());// "你好,我也是一个实例" console.log (Bar.classMethod ());// "你好,我是静态的"

同样,你可以使用super来调用父构造函数:

class Foo {}

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

当然你也可以用它来访问父类属性super。prop。 所以,使用ES6,快乐吧。

其他回答

虽然您可以通过父方法的原型调用父方法,但您将需要传递当前的子实例以使用调用、应用或绑定方法。bind方法会创建一个新函数,所以如果你关心性能,我不建议你这样做,除非它只被调用一次。

作为一种替代方法,您可以替换子方法,并在调用原始子方法时将父方法放在实例上。

function proxy(context, parent){ var proto = parent.prototype; var list = Object.getOwnPropertyNames(proto); for(var i=0; i < list.length; i++){ var key = list[i]; // Create only when child have similar method name if(context[key] !== proto[key]){ let currentMethod = context[key]; let parentMethod = proto[key]; context[key] = function(){ context.super = parentMethod; return currentMethod.apply(context, arguments); } } } } // ========= The usage would be like this ========== class Parent { first = "Home"; constructor(){ console.log('Parent created'); } add(arg){ return this.first + ", Parent "+arg; } } class Child extends Parent{ constructor(b){ super(); proxy(this, Parent); console.log('Child created'); } // Comment this to call method from parent only add(arg){ return super.add(arg) + ", Child "+arg; } } var family = new Child(); console.log(family.add('B'));

更灵活的答案与经典的js。

你在子类中定义了"_parent = A.prototype;",然后你可以用apply调用父类的方法:

A类{ _msg = ' A '; _msgOnlyA='伟大的来自A'; 构造函数(){ } 你好(){ console.log('你好' +。_msg +”、“+ this._msgOnlyA); } }; 类B扩展A{ _parent = A.prototype; _msg = ' B '; 构造函数(){ 超级(); } 你好(){ this._parent.hello。应用(这个参数); console.log('你好' + this._msg); } }; var b = new b (); b.hello ();

对于多级原型查找,有一个更简单、更紧凑的解决方案,但它需要Proxy支持。用法:SUPER(<实例>).<方法>(<参数>),例如,假设两个类A和B用方法m扩展了A: SUPER(新B).m()。

function SUPER(instance) {
    return new Proxy(instance, {
        get(target, prop) {
            return Object.getPrototypeOf(Object.getPrototypeOf(target))[prop].bind(target);
        }
    });
}

以Douglas Crockford的想法为基础

    function Shape(){}

    Shape.prototype.name = 'Shape';

    Shape.prototype.toString = function(){
        return this.constructor.parent
            ? this.constructor.parent.toString() + ',' + this.name
            : this.name;
    };


    function TwoDShape(){}

    var F = function(){};

    F.prototype = Shape.prototype;

    TwoDShape.prototype = new F();

    TwoDShape.prototype.constructor = TwoDShape;

    TwoDShape.parent = Shape.prototype;

    TwoDShape.prototype.name = '2D Shape';


    var my = new TwoDShape();

    console.log(my.toString()); ===> Shape,2D Shape

ES6风格允许您使用新功能,如超级关键字。super关键字,当你使用ES6类语法时,它都是关于父类上下文的。作为一个非常简单的例子,签出:

记住:我们不能通过实例方法中的super关键字调用父静态方法。调用方法也应该是静态的。

通过实例方法调用静态方法- TypeError ! 类Foo { static classMethod() { 返回“你好”; } } 类Bar扩展Foo { classMethod () { return super.classMethod() + ', too'; } } console.log (Bar.classMethod ());// 'hello' -调用继承的静态方法 console.log(())(新酒吧.classMethod ());// 'Uncaught TypeError' -调用一个实例方法

通过super调用静态方法-这是有效的!

类Foo { static classMethod() { 返回“你好”; } } 类Bar扩展Foo { static classMethod() { return super.classMethod() + ', too'; } } console.log (Bar.classMethod ());// 'hello, too'

现在,超级上下文基于调用而改变——瞧!

类Foo { static classMethod() { 返回'hello I am static only'; } classMethod () { 返回'hello there I am an instance '; } } 类Bar扩展Foo { classMethod () { return super.classMethod() + ', too'; } } console.log(())(新酒吧.classMethod ());// "你好,我也是一个实例" console.log (Bar.classMethod ());// "你好,我是静态的"

同样,你可以使用super来调用父构造函数:

class Foo {}

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

当然你也可以用它来访问父类属性super。prop。 所以,使用ES6,快乐吧。