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

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

我使用下面的代码在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中完成的。

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


当前回答

以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

其他回答

Well in order to do this, you are not limited with the Class abstraction of ES6. Accessing the parent constructor's prototype methods is possible through the __proto__ property (I am pretty sure there will be fellow JS coders to complain that it's depreciated) which is depreciated but at the same time discovered that it is actually an essential tool for sub-classing needs (especially for the Array sub-classing needs though). So while the __proto__ property is still available in all major JS engines that i know, ES6 introduced the Object.getPrototypeOf() functionality on top of it. The super() tool in the Class abstraction is a syntactical sugar of this.

因此,如果你没有访问父构造函数的名称,并且不想使用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);
    }
}

更灵活的答案与经典的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 ();

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,快乐吧。

以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

下面是一种让子对象使用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');