首页 > 解决方案 > JS 中的 3 种继承类型 & [.isPrototypeOf()] 结果的差异

问题描述

我相信在Javascript OOP中实现“继承”的方法不止三种。

也许我把这些代码写错了,但是我的代码的结果是用不同的方式操作的。

(环境是 V8)


   /**
     * Type 1 : "new" Keyword
    */

    //Parent
    function newParent(a,b){
        this.a = a;
        this.b = b;
    }
    newParent.prototype = {
        print : function() {
            return this.a + '/' + this.b
        }
    }

    //Child
    function newChild(a,b,c) {
        newParent.call(this,a,b);
        this.c = c;
        this.callC = function(){
            return this.c;
        }
    }

    newChild.prototype = new newParent();

    var O = new newChild(1,2,3);
    console.log(O instanceof newChild); //true
    console.log(O instanceof newParent); //true

中的new关键字newChild.prototype = new newParent();


/**
 * Type 2 : "Object.create()" 
*/

//Parent
function ocParent(a,b){
    this.a = a;
    this.b = b;
}
ocParent.prototype = {
    print : function() {
        return this.a + '/' + this.b
    }
}

//Child
function ocChild(a,b,c) {
    ocParent.call(this,a,b);
    this.c = c;
    this.callC = function(){
        return this.c;
    }
}

ocChild.prototype = Object.create(ocParent.prototype);
ocChild.prototype.constructor = ocChild;

var OO = new ocChild(1,2,3);
console.log(OO instanceof ocChild); //true
console.log(OO instanceof ocParent); //true

中的Object.create()方法ocChild.prototype = Object.create(ocParent.prototype);。另外,我将损坏 .constructor的连接到ocChild.


最后一个是最新的(?)形式。

/**
 * Type 3 : Class-extends Keyword
*/
class PParent {
    constructor(a,b) {
        this.a = a;
        this.b = b;
    }
    get print() { //For call this method, Just use '<instance>.print' only.
        return this.a + '/' + this.b;
    }
}

class CChild extends PParent {
    constructor(a,b,c) {
        super(a,b);
        this.c = c;
    }
    get callC() { //For call this method, Just use '<instance>.callC' only.
        return this.c;
    }
}

var OOO = new CChild(1,2,3);
console.log(OOO instanceof CChild); //true
console.log(OOO instanceof PParent); //true

全部<instance_name> instanceof <constructor_name>返回true。但是, ,的.isprototypeOf()结果 是这样的。OOOOOO

PParent.isPrototypeOf(CChild)
> true
newParent.isPrototypeOf(newChild)
> false
ocParent.isPrototypeOf(ocChild);
> false

为什么这些结果不同?

标签: javascript

解决方案


这是因为您的前两个方法没有初始化class语法所做的静态原型链:

/**
 * Type 1 : "new" Keyword
 */

//Parent
function NewParent(a, b) {
  this.a = a;
  this.b = b;
}
NewParent.prototype = {
  print: function() {
    return this.a + '/' + this.b
  }
}

//Child
function NewChild(a, b, c) {
  NewParent.call(this, a, b);
  this.c = c;
  this.callC = function() {
    return this.c;
  }
}

Object.setPrototypeOf(NewChild, NewParent); // this line!
NewChild.prototype = new NewParent();

var O = new NewChild(1, 2, 3);
console.log(O instanceof NewChild); //true
console.log(O instanceof NewParent); //true
console.log(NewParent.isPrototypeOf(NewChild)); //true

/**
 * Type 2 : "Object.create()" 
 */

//Parent
function OcParent(a,b){
    this.a = a;
    this.b = b;
}
OcParent.prototype = {
    print : function() {
        return this.a + '/' + this.b
    }
}

//Child
function OcChild(a,b,c) {
    OcParent.call(this,a,b);
    this.c = c;
    this.callC = function(){
        return this.c;
    }
}

Object.setPrototypeOf(OcChild, Object.create(OcParent)); // this line!
OcChild.prototype = Object.create(OcParent.prototype);
OcChild.prototype.constructor = OcChild;

var OO = new OcChild(1,2,3);
console.log(OO instanceof OcChild); //true
console.log(OO instanceof OcParent); //true
console.log(OcParent.isPrototypeOf(OcChild)); //true

我并不是说它们中的任何一个都与class语法的工作方式相同,只是它们现在以一种已确认的方式初始化静态原型链isPrototypeOf()


推荐阅读