前言
继承是js作为面向对象的语言最为重要的一个特性之一,也是面试中经常被问到的一个知识点
继承主要是为了子类可以使用父类的所有功能,并且能对这些功能进行扩展。
1.原型继承
function Parent1() {
this.name = "parent1"
this.arr = [1,2,3]
}
Parent1.prototype.say = function(){
console.log(this.name);
}
function Child1 (){
this.type = "child1"
}
Child1.prototype = new Parent1()
let child1_1 = new Child1()
let child1_2 = new Child1()
console.log(child1_1.name); // parent1
console.log(child1_1.say()); //parent1
child1_2.arr.push(4)
console.log(child1_1.arr,child1_2.arr); //[ 1, 2, 3, 4 ] [ 1, 2, 3, 4 ]
方式:将子类的原型挂载到父类上 缺点:子类都是通过new构造处理的实例,父类属性没有隔离,会相互影响
2.构造函数继承
function Parent2 (){
this.name = "parent2"
}
Parent2.prototype.say = function(){
console.log(this.name);
}
function Child2 (){
this.type = "child2"
Parent2.call(this)
}
let child2_1 = new Child2()
console.log(child2_1.say()); // TypeError: child2_1.say is not a function
console.log(child2_1.name); // parent2
方式:通过call、apply、bind将子类函数的this指向父类函数 缺点:只能读取到父类函数的属性,无法继承原型链上的方法和属性
3.组合继承
function Parent3 (){
this.name = "parent3"
this.arr = [1,2,3]
}
Parent3.prototype.say = function(){
console.log(this.name);
}
function Child3 (){
this.type = "child3"
Parent3.call(this)
}
Child3.prototype = new Parent3()
let child3_1 = new Child3()
let child3_2 = new Child3()
child3_1.arr.push(4)
console.log(child3_1.arr, child3_2.arr);
方式:通过原型继承和构造继承的组合使用 缺点:call()方法已经拿到父类所有的属性 ,后面再使用原型时也会有父类所有属性;
4.寄生组合继承
function Parent4 (){
this.name = "parent3"
this.arr = [1,2,3]
}
Parent4.prototype.say = function(){
console.log(this.name);
}
function Child4 (){
this.type = "child4"
Parent4.call(this)
}
Child4.prototype = Parent4.prototype
Child4.prototype.constructor = Child4
let child4_1 = new Child4()
let child4_2 = new Child4()
child4_1.arr.push(4)
console.log(child4_1.arr, child4_2.arr) // [1, 2, 3, 4] [1, 2, 3]
console.log(child4_1.constructor === Child4) // true
console.log(child4_1.constructor === Parent4)// false
说明:解决组合继承重复属性的问题,直接将子类的原型等于父类的原型,或者是用Object.create继承原型但不执行父类构造函数;
5.ES6 class继承
class Parent5{
constructor(){
this.name = 'Parent5'
this.arr = [1, 2, 3]
}
say(){
console.log(this.name)
}
}
class Child5 extends Parent5{
constructor(){
super() //通过super()调用父类构造函数
this.type="Child5"
}
}
let child5_1 = new Child5()
let child5_2 = new Child5()
child5_1.arr.push(4)
console.log(child5_1.say()) // Parent5
console.log(child5_1.arr, child5_2.arr) // [1, 2, 3, 4] [1, 2, 3]
console.log(child5_1.constructor === Child5) // true
console.log(child5_2.constructor === Parent5) // false
就是寄生组合继承的语法糖