一文搞懂js中的继承

2021-03-01  本文已影响0人  pumpkin1024

原型链继承(Prototypal inheritance)

1. [[Prototype]] (对象的属性)

2. prototype (函数的属性)

function Parent(){
    this.flag = true;
    this.arr = [];
}
function Child(){}
console.log(Child.prototype.constructor);// Child
// 会修改Child.prototype的constructor指向
Child.prototype = new Parent();// 原型链继承
console.log(Child.prototype.constructor);// Parent
const child1 = new Child();
const child2 = new Child();

// 非引用类型不影响
console.log(child1.flag);// true
console.log(child2.flag);// true
child2.flag = false;
console.log(child1.flag);// true
console.log(child2.flag);// false

// 缺点1:引用数据类型共享,修改了child2的arr值,所有实例的值都改变
console.log(child1.arr);// []
console.log(child2.arr);// []
child2.arr.push(1);
console.log(child1.arr);// [1] 
console.log(child2.arr);// [1]
// 缺点2:无法向Parent传参

借用构造函数继承(经典继承)

function Parent(){
   this.flag = true;
   this.arr = [];
}
Parent.prototype.getFlag = function(){}
function Child(){
    Parent.call(this); // 借用构造函数继承
}
// 无法继承Parent prototype的方法 
// 因为prototype只在new时有用
// child1只是Child的实例,而非Parent的实例
const child1 = new Child();
console.log(child1 instanceof Parent);// false

组合继承(原型链+经典)

// 缺点,调用2次父类构造函数
function Parent(){
   this.flag = true;
   this.arr = [];
}
Parent.prototype.getFlag = function(){}
function Child(){
    // 通过经典继承继承实例属性的继承
    Parent.call(this); // 借用构造函数继承
}
// 通过原型链继承prototype方法的继承
Child.prototype = new Parent();// 原型链继承

原型式继承

  1. 接受一个对象A
  2. 返回一个新对象B
  3. 并且B.proto --> A
// 相当于Object.create()
function createObjcet(obj) {
  function F () {};
  F.prototype = obj;
  return new F();
}

寄生式继承

function createObjcet(obj) {
  function F () {};
  F.prototype = obj;
  return new F();
}
function wraop(o){
    var obj = createObjcet(o);
    // 在原型式继承的基础上新增一些函数或属性
    obj.sayName = function(){ 
        console.log(this.name);
    }
    return obj;
}

寄生组合式继承(经典+原型式继承)

function createObjcet(obj) {
  function F () {};
  F.prototype = obj;
  return new F();
}
function Parent(){
   this.flag = true;
   this.arr = [];
}
Parent.prototype.getFlag = function(){}
function Child(){
    // 通过经典继承继承实例属性的继承
    Parent.call(this); // 借用构造函数继承
}
// 通过原型式继承prototype方法的继承
Child.prototype = createObjcet(Parent.prototype);
// 修正constructor
Child.prototype.constructor = Child;

参考文章

上一篇下一篇

猜你喜欢

热点阅读