1.原型链方式
基本思想:利用原型让一个引用类型继承另外一个引用类型的属性和方法。
构造函数,原型,实例之间的关系:每个构造函数都有一个原型对象,原型对象包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。
原型链实现继承例子:
function Father() {
this.property = true;
}
Father.prototype.getSuperValue = function () {
return this.property;
};
function Son() {
this.property = false;
}
//继承了Father
Son.prototype = new Father();
Son.prototype.getSubValue = function () {
return this.property;
};
var instance = new Son();
console.log(instance.getSuperValue()); //true
优点:
简单易于实现,父类的新增的实例与属性子类都能访问
缺点:
可以在子类中增加实例属性,如果要新增加原型属性和方法需要在 new 父类构造函数的后面
无法实现多继承
创建子类实例时,不能向父类构造函数中传参数
2.借用构造函数(伪造对象、经典继承)
基本思想:在子类型构造函数的内部调用超类构造函数,通过使用 call()和 apply()方法可以在新创建的对象上执行构造函数。
例子:
function Father() {
this.colors = ["red", "blue", "green"];
}
function Son() {
Father.call(this); //继承了Father
}
var instance1 = new Son();
instance1.colors.push("black");
console.log(instance1.colors); //"red","blue","green","black"
var instance2 = new Son();
console.log(instance2.colors); //"red","blue","green"
优点:
解决了子类构造函数向父类构造函数中传递参数
可以实现多继承(call 或者 apply 多个父类)
缺点:
方法都在构造函数中定义,无法复用
不能继承原型属性/方法,只能继承父类的实例属性和方法
3.ES6 class
代码量少,易懂
//class 相当于es5中构造函数
//class中定义方法时,前后不能加function,全部定义在class的protopyte属性中
//class中定义的所有方法是不可枚举的
//class中只能定义方法,不能定义对象,变量等
//class和方法内默认都是严格模式
//es5中constructor为隐式属性
class People {
constructor(name = "wang", age = "27") {
this.name = name;
this.age = age;
}
eat() {
console.log(`${this.name} ${this.age} eat food`);
}
}
//继承父类
class Woman extends People {
constructor(name = "ren", age = "27") {
//继承父类属性
super(name, age);
}
eat() {
//继承父类方法
super.eat();
}
}
let wonmanObj = new Woman("xiaoxiami");
wonmanObj.eat();