原型链继承
- 将子类的原型对象指向父类的实例
- 优点:继承了父类的模板,又继承了父类的原型对象
- 缺点:
- 无法实现多继承(因为已经指定了原型对象了)
- 父类的所有 引用属性(info)会被所有子类共享,更改一个子类的引用属性,其他子类也会受影响
- 创建子类时,无法向父类构造函数传参数
1function Parent() {
2 this.info = {
3 name: 'Parent',
4 age: 18,
5 }
6}
7
8Parent.prototype.getInfo = function () {
9 console.log(this.info)
10}
11
12function Child() {}
13
14// 将子类的原型对象指向父类的实例
15Child.prototype = new Parent()
16
17let child = new Child()
18child.info.gender = 'M'
19child.getInfo() // { name: 'Parent', age: 18, gender: 'M' }
构造函数继承
- 在子类构造函数内部使用
apply
或 call
来调用父类构造函数,复制父类的实例属性给子类
- 优点:
- 解决了原型链继承中子类实例共享父类引用对象的问题,实现多继承
- 创建子类实例时,可以向父类传递参数
- 缺点:
- 构造继承只能继承父类的实例属性和方法,不能继承父类原型的属性和方法(方法属性写在构造函数中,每次创建示例都会被初始化)
1function Parent(name) {
2 this.info = {
3 name,
4 hobby: ['football', 'basketball'],
5 }
6}
7
8Parent.prototype.getInfo = function () {
9 console.log(this.info)
10}
11
12function Child(name, age) {
13 // 继承父类属性
14 Parent.call(this, name)
15 this.age = age
16}
17
18// 继承父类方法
19Child.prototype = new Parent()
20
21let child1 = new Child('wujie1', 19)
22child1.info.hobby.push('soccer')
23console.log(child1.getInfo()) // { name: 'wujie1', hobby: [ 'football', 'basketball', 'soccer' ] }
24console.log(child1.age)
25
26let child2 = new Child('wujie2', 20)
27console.log(child2.getInfo()) // { name: 'wujie2', hobby: [ 'football', 'basketball' ] }
28console.log(child2.age)
组合继承
- 使用原型链继承保证子类继承父类原型的属性和方法
- 使用构造继承保证子类继承父类实例的属性和方法
1function Parent(name) {
2 this.info = {
3 name,
4 hobby: ['football', 'basketball'],
5 }
6}
7
8Parent.prototype.getInfo = function () {
9 console.log(this.info)
10}
11
12function Child(name, age) {
13 // 继承父类属性
14 Parent.call(this, name)
15 this.age = age
16}
17
18// 继承父类方法
19Child.prototype = new Parent()
20
21let child1 = new Child('wujie1', 19)
22child1.info.hobby.push('soccer')
23console.log(child1.getInfo()) // { name: 'wujie1', hobby: [ 'football', 'basketball', 'soccer' ] }
24console.log(child1.age)
25
26let child2 = new Child('wujie2', 20)
27console.log(child2.getInfo()) // { name: 'wujie2', hobby: [ 'football', 'basketball' ] }
28console.log(child2.age)
原型式继承
1let parent = {
2 name: 'parent',
3 hobby: ['football', 'basketball'],
4}
5
6let child = Object.create(parent)
7child.name = 'child'
8child.hobby.push('soccer')
9
10console.log(child.name) // child
11console.log(child.hobby) // [ 'football', 'basketball', 'soccer' ]
寄生式继承
- 通过获取对象的浅拷贝,再对浅拷贝方法增强(添加方法),也就是在原型式寄生的基础上再添加方法
1let parent = {
2 name: 'parent',
3 hobby: ['football', 'basketball'],
4}
5
6function clone(original) {
7 let clone = Object.create(original)
8 clone.getHobby = function () {
9 return this.hobby
10 }
11 return clone
12}
13
14let child = clone(parent)
15child.name = 'child'
16child.hobby.push('soccer')
17
18console.log(child.name) // child
19console.log(child.hobby) // [ 'football', 'basketball', 'soccer' ]
20console.log(child.getHobby()) // [ 'football', 'basketball', 'soccer' ]
寄生组合式继承
- 将组合继承,寄生式继承组合起来实现的继承,是所有继承方式的最优解
- 优点:解决了组合继承父类会被调用两次和属性在不同层级会重复的问题
1function Parent() {
2 this.name = 'parent'
3 this.hobby = ['football', 'basketball']
4}
5
6Parent.prototype.getHobby = function () {
7 return this.hobby
8}
9
10function Child() {
11 Parent.call(this)
12 this.friend = 'child friends'
13}
14
15function clone(parent, child) {
16 child.prototype = Object.create(parent.prototype)
17 child.prototype.constructor = child
18}
19
20clone(Parent, Child)
21
22Child.prototype.getFriend = function () {
23 return this.friend
24}
25
26let child = new Child()
27console.log(child.getHobby()) // [ 'football', 'basketball' ]
28console.log(child.getFriend()) // child friend
class 继承
1class Parent {
2 constructor(name) {
3 this.name = name
4 }
5 getName() {
6 console.log(this.name)
7 }
8}
9class Child extends Parent {
10 constructor(name) {
11 super(name)
12 this.age = 18
13 }
14}