Appearance
继承是很经典的面试问题,今天我们来现在整体总结一下
ES6继承
js
class Parent {
constructor(name){
this.name = name
}
sayHi(){
console.log('HI~~~')
}
}
class Child extends Parent {
constructor(name,type){
super(name)
this.type = type
}
sayHello(){
console.log('hello')
}
}
const c1 = new Child('c1','child')
console.log(c1.name,c1.type)
c1.sayHi()ES5 继承
注意,在es6之前,没有class 类语法
原型链继承
js
function Person(name) {
this.name = name || '父类';
this.hobby = ['eat','sleep']
}
// 将需要共享的方法放在父类原型上
Person.prototype.sayHello = function(name){
console.log(`Hello, my name is ${name}`);
}
function Child(like){
this.like = like
}
Child.prototype = new Person() // 此时,Child.prototype.constructor = Person
Child.prototype.constructor = Child //修正constructor指向
const child = new Child('football')
child.sayHello('child') // Hello, my name is child
console.log(child.like,child.hobby) // football [ 'eat', 'sleep' ] 父类
const child1 = new Child('football')
const child2 = new Child('piano')
child1.hobby.push('code')
child1.name = 'child1'
child2.name = 'child2'
console.log(child1.name,child2.name) // child1 child2
console.log(child1.hobby,child2.hobby) //[ 'eat', 'sleep', 'code' ] [ 'eat', 'sleep', 'code' ]优点:共享了父类构造函数的方法 缺点:1. 不能向父类构造函数传参,如name; 2. 子类实例共享父类构造函数的引用属性(arr) 注意:修改child1的name属性,是不会影响到child2.name。因为设置child1.name相当于在⼦类实例新增了name属性。
借用构造函数继承
js
function Parent(name){
this.name = name
this.hobby = ['football','piano']
this.sayName = function(){
console.log('hello' + this.name);
}
}
function Child(name,age){
Parent.call(this,name),
this.age = age
}
const child1 = new Child('child1',18)
const child2 = new Child('child2',28)
child1.hobby.push('coding')
Parent.prototype.sayHello = function(){
console.log('hello');
}
console.log(child1.hobby,child2.hobby) // [ 'football', 'piano', 'coding' ] [ 'football', 'piano' ]
console.log(child1.sayName==child2.sayName) // false 说明每个实例的sayName都是独立的
child1.sayHello() //child1.sayHello is not a function优点:可以向父类构造函数传参; 实例之间相互独立;不共享父类构造函数的方法 缺点:方法不能复用;不能获得父类原型上的方法;
组合继承
js
function Parent(name){
this.name = name;
this.hobby = ['football','piano'];
}
Parent.prototype.sayHello = function(){
console.log('hello');
}
function Child(name,age){
Parent.call(this,name);
this.age = age;
}
Child.prototype = new Parent()
Child.prototype.constructor = Child
const child1 = new Child('zhangsan',18)
const child2 = new Child('lisi',20)
child1.hobby.push('swimming')
console.log(child1.hobby) // [ 'football', 'piano', 'swimming' ]
console.log(child2.hobby) // [ 'football', 'piano' ]
console.log(child1.sayHello == child2.sayHello) // true
child1.sayHello() // hello优点:可以向父类构造函数传参;不共享父类构造函数中的引用类型属性;可以公用父类原型对象中的方法 缺点:调用了两次父类构造函数,会存在一份多余的父类构造函数实例
寄生组合继承(完美解决方案)
javascript
function Parent(name){
this.name = name
this.hobby = ['football','piano']
}
Parent.prototype.sayHello = function(){
console.log('hello')
}
function Child(name,age){
Parent.call(this,name)
this.age = age
}
Child.prototype =Object.create(new Parent())
Child.prototype.constructor = Child那么es6 的继承经过babel转换后是那种es5的继承呢? 当然是寄生组合继承,其中 Parent.call(this,name)模拟super关键字