JS中继承的几种实现方式

继承的核心就是将父类的原型(prototype)赋值给子类,同时将构造函数(constructor)指回子类,既保证了不会有多余的父类属性,又保证子类能找到自身的构造函数。

1.原型链的继承

 1 function Father(){
 2   this.firstName = 'wang',
 3   this.action = function(){
 4     console.info('super')
 5   }
 6 }
 7 Father.prototype.sayHi = function(){
 8   console.info('hi')
 9 }
10 // 子类的原型指向父类的原型
11 Son.prototype = Father.prototype
12 Son.prototype.constructor = Son // 需要手动将constructor指回来,不然构造函数指向父类
13 // 子类只能继承父类原型上的属性和方法,不能继承父类本身的属性
14 let s = new Son()
15 s.sayHi() // hi
16 console.info(s.firstName) //获取不到父类自身的属性,undefined
17 console.info(s.action) //获取不到父类自身的属性,undefined
弊端:需要手动改回constructor,不能继承父类自身属性
 
基于原型的继承还有一种实现:
 1 function Father(){
 2   this.data = [1]
 3   this.firstName = 'wang',
 4   this.action = function(){
 5     console.info('super')
 6   }
 7 }
 8 Father.prototype.sayHi = function(){
 9   console.info('hi')
10 }
11 function SonOther(){
12 }
13 SonOther.prototype = new Father()
14 SonOther.prototype.constructor = SonOther
15 let so1 = new SonOther()
16 let so2 = new SonOther()
17 // 能继承父类自身的属性
18 console.info(so1.firstName) // wang
19 so2.sayHi()  // hi
20 // 但是数据是共享的
21 so1.data.push(2)
22 console.info(so2.data) // [1, 2] 
弊端:需要手动改回constructor,子类对象属性共享

2.借助构造函数继承

1 function Son(){
2   Father.call(this) // Father.apply(this)
3 }
4  
5 let s = new Son()
6 let s2 = new Son()
7 console.info(s.data.push(2))
8 console.info(s.data, s2.data) // [ 1, 2 ] [ 1 ] 不会共享数据
9 console.info(s.sayHi) // 不能继承父类原型中的方法 
弊端:只能继承父类自身的属性

3.组合式继承   构造函数+原型链

1 function Son(){
2   Father.call(this) // Father.apply(this)
3 }
4  
5 Son.prototype = new Father() 
优点:能继承父类自身及原型链上的方法
弊端:调用了两次父类的构造函数,造成内存浪费

4.寄生式继承

通过一个函数在内部给对象添加属性和方法
 1 let father = {
 2   name: 'f',
 3   age: 30
 4 }
 5  
 6 function createObj(original){
 7   let obj = Object.create(original)
 8   obj.sayHi = function(){
 9     console.info('hi')
10   }
11   return obj
12 }
13  
14 let s = createObj(father)
15 console.info(s.name)
16 s.sayHi()
17  
弊端:子类对象共享属性

5.寄生组合继承

 1 function inheritPrototype(subType, superType){
 2   let prototype = Object.create(subType.prototype)
 3   subType.prototype = prototype
 4   subType.prototype.constructor = subType
 5 }
 6  
 7 function Son(){
 8   Father.call(this)
 9 }
10 inheritPrototype(Son, Father)
11  
12 let son = new Son()
13 console.info(son)

6.类的继承

要点:使用extends指明父类,构造函数中写super
 1 class Parent {
 2   constructor(){
 3     this.name = 'f'
 4   }
 5   sayHi(){
 6     console.info('hi')
 7   }
 8 }
 9  
10 class Child extends Parent {
11   constructor(value){
12     super(value)
13     this.val = value
14   }
15 }
16  
17 let child = new Child('899.5')
18 console.info(child.name, child.val) // f 899.5
19 child.sayHi() // hi

 

posted on 2020-08-06 13:38  橘生淮南_  阅读(237)  评论(0编辑  收藏  举报