首页 > 技术文章 > js继承方式及特征

Paul-Yellow 2021-04-13 12:45 原文

1. 原型链继承 (原型链)

function Parent() {
this.fruits = ['apple', 'orange'];
}
Parent.prototype.sayHello = function () {
console.log('Parent');
};

function Child() {}

Child.prototype = new Parent();

let child1 = new Child();
child1.fruits.push('banana');
console.log(child1.fruits); // [ 'apple', 'orange', 'banana' ]

let child2 = new Child();
console.log(child2.fruits); // [ 'apple', 'orange', 'banana' ]

特点:被所有的实例共享了引用类型属性


2. 构造函数方式的继承 (call)

function Parent() {
this.fruits = ['apple', 'orange'];
}
Parent.prototype.sayHello = function () {
console.log('Parent');
};

function Child() {
Parent.call(this);
}

let child1 = new Child();
child1.fruits.push('banana');
console.log(child1.fruits); // [ 'apple', 'orange', 'banana' ]

let child2 = new Child();
console.log(child2.fruits); // [ 'apple', 'orange' ]

特点:

  1. call方法仅仅调用了父级构造函数的属性及方法(私有属性),没有办法调用父级构造函数原型对象的方法(公有属性)
  2. 可以在 Child 中向 Parent 传参
  3. 每次实例化对象都得创建一遍方法,基本无法实现函数复用

3. 组合链继承方式 (原型链 + call)

function Parent(name) {
  this.name = name;
  this.fruits = ['apple', 'orange'];
}
Parent.prototype.sayHello = function () {
  console.log(this.name);
};

function Child(name, age) {
  Parent.call(this, name);
  this.name = age;
}
Child.prototype = new Parent();

let child1 = new Child();
child1.fruits.push('banana');
console.log(child1.fruits); // [ 'apple', 'orange', 'banana' ]

let child2 = new Child();
console.log(child2.fruits); // [ 'apple', 'orange' ]

特点:

  1. 子类的私有属性继承了父类私有属性,子类公有属性也继承了父类的私有属性和公有属性
  2. 父类函数执行了两次

4. 寄生继承 (Object.create 或者是自我实现的Object)

let parent = {
  fruits: ['apple', 'orange'],
  sayHello: function () {
    console.log('hello');
  },
};

function parasitic(pro) {
  let clone = Object.create(pro);
  return clone;
}

let child1 = parasitic(parent);
child1.fruits.push('banana');
console.log(child1.fruits); // [ 'apple', 'orange', 'banana' ]

let child2 = parasitic(parent);

这里用到了Object.create

特点:

  1. 和原型链继承效果雷同

5. 寄生组合继承(Oject.create + call)

function Parent(name) {
    this.name = name;
    this.fruits = ['apple','orange']
    
}
Parent.prototype.sayHello = function () {
    console.log(this.name)
}

function Child() {
    Parent.call(this)
    
}
function parasitic(child,parent) {
    let tempObj = Object.create(parent.prototype);
    child.prototype = tempObj;
    tempObj.constructor = child; 
}

parasitic(Child, Parent);


特点:

  1. 子类私有属性继承了父类的私有属性,子类公有属性继承了父类公有属性(和组合继承相比更加纯粹干净)

总结: 所以应用的最多应该就是 组合继承和寄生组合继承两种方式了

推荐阅读