js继承方式

91 阅读2分钟

先写一个父类,代码如下:

// 定义一个父类
function Parent (name) {
  // 属性
  this.name = name;
  // 实例方法
  this.sleep = function(){
    console.log(this.name + '正在睡觉!');
  }
}
// 原型方法
Parent.prototype.eat = function(food) {
  console.log(this.name + '正在吃:' + food);
};

1、原型链继承

核心:  将父类的实例作为子类的原型

function Child(){ 
    
}
Child.prototype = new Parent();
Child.prototype.name = 'son1';

// Test Code
var son1 = new Child();
console.log(son1.name); //son1
console.log(son1.eat('肉')); //son1正在吃肉
console.log(son1 instanceof Child); //true 
console.log(son1 instanceof Parent); //true

特点:

  1. 实例可继承的属性有:实例的构造函数的属性,父类构造函数属性,父类原型的属性
  2. 简单,易于实现 缺点:
  3. 无法实现多继承
  4. 新实例无法向父类构造函数传参
  5. 所有新实例都会共享父类实例的属性。(原型上的属性是共享的,一个实例修改了原型属性,另一个实例的原型属性也会被修改!)

2、构造函数继承

核心: 使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类(没用到原型)

function Child(){ 
  Parent.call(this,"son2"); 
  this.age = "12";
}
var son2 = new Child();
console.log(son2.name); //'son2'
console.log(son2.age); //12

特点:

  1. 可以实现多继承(call多个父类对象)
  2. 在子实例中可向父实例传参 缺点:
  3. 只能继承父类构造函数的属性,没有继承父类原型的属性/方法
  4. 无法实现构造函数的复用。(每次用每次都要重新调用)
  5. 每个新实例都有父类实例函数的副本,影响性能

3、寄生组合继承

核心: 通过寄生方式(在函数内返回对象然后调用),砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性

function Child(taskName){
    Parent.call(this,"son3");
    this.task = taskName;
}
Child.prototype = Object.create(Parent.prototype);
//上面这行代码等价于下面这个create
//function create(obj){
   //function fn(){};
   //fn.prototype = obj;
   //return new fn();
//}
//create(Parent.prototype);

Child.prototype.constructor = Child;
Child.prototype.study = function(){
    console.log(this.name + "学" + this.task);
   
}
let son3 = new Child("美术");
console.log(son3.name);

特点: 完美解决了其他继承方式的缺点

缺点: 实现较为复杂