js中7種繼承的實現和優缺點
阿新 • • 發佈:2019-03-13
原型鏈 副本 obj 無法 line 衍生 組合 不存在 所有
原型鏈繼承
function Parent(){ this.name = ‘kevin‘ } Parent.prototype.getName = function(){ console.log(this.name) } function Child(){ } Child.prototype = new Parent() var child = new Child() console.log(child.name) //kevin
優點:
- 簡單,容易實現
缺點:
- 來自父類原型對象的引用屬性是所有子類實例共享的
- 創建子類實例時,無法向父類構造函數傳參
借用構造函數(經典繼承)
function Parent(name){ this.name = name } function Child(name){ Parent.call(this,name) } let child = new Child(‘Tom‘) let child1 = new Child(‘Jack‘) console.log(child.name) //Tom console.log(child1.name) //Jack
優點:
- 解決了子類型實例共享父類引用屬性的問題
- 創建子類實例時,可以向父類構造函數傳參
缺點:
- 無法實現函數復用 ,方法在構造函數中定義,每次創建子類實例都會創建一個新方法,占用內存
組合繼承(原型鏈繼承和經典繼承的雙劍合璧)
function Parent(name){ this.name = name this.color = [‘red‘,‘bule‘,‘green‘] } Parent.prototype.getName = function(){ console.log(this,name) } function Child(name,age){ this.age = age Parent.call(this,name) } Child.prototype = new Parent() Child.prototype.constructor = Child Child.prototype.getAge = function(){ console.log(this.age) } let child = new Child(‘Tom‘,12) console.log(child.name) //Tom child.getAge() //12 child.color.push(‘blcak‘) console.log(child.color) //[‘red‘,‘bule‘,‘green‘,‘black‘] let child1 = new Child(‘Jack‘,18) console.log(child1.name) //Jack child1.getAge() //18 console.log(child1.color) //[‘red‘,‘bule‘,‘green‘]
優點:
- 不存在父類引用屬性共享問題
- 可以給父類構造函數傳參
- 通過原型屬性設置方法,使得函數可復用
- 最常用的繼承方式
缺點(小瑕疵):
- 子類調用了兩次父類構造函數,生成了兩個父類實例,第二次調用改變了指向第一個實例的指針,使得第一個實例變得多余了
原型式繼承
function object(o){ function F(){} F.prototype = o return new F() } //在ES5中有了新方法代替Object.created(o,{name:‘Ton‘等新屬性}) let person = { name:‘Tom‘, color : [‘red‘,‘bule‘,‘green‘] } let person1 = Object.create(person) let person2 = Object.create(person) person1.name = ‘Jack‘ person1.color.push(‘black‘) person2.name = ‘Kevin‘ person1.color.push(‘yellow‘) console.log(person1.name) //Jack console.log(person2.name) //Kevin console.log(person1.color == person2.color) //true
優點:
- 從已有對象衍生新對象,不需要創建自定義類型,更像是對象復制
缺點:
- 原型引用的屬性被實例所共享
- 無法實現代碼復用
寄生式繼承
let person = { name:‘Tom‘, color : [‘red‘,‘bule‘,‘green‘] } function createAnother(o){ let clone = create(o) clone.getName(){ console.log(this.name) } return clone //clone這個對象不僅有原型引用屬性,還有自己的方法 } let person1 = createAnother(person) person1.getName() //Tom
優點:
- 不需要創建自定義類型
缺點:
- 原型引用的屬性被實例所共享
- 無法實現代碼復用
##寄生組合式繼承(最佳方式)
function Parent (name) { this.name = name; this.colors = [‘red‘, ‘blue‘, ‘green‘]; } Parent.prototype.getName = function () { console.log(this.name) } function Child (name, age) { Parent.call(this, name); this.age = age; } function prototype(Child,Parent){ //獲得父類型原型上的方法 let prototype = object(Parent.prototype) //創建父類型原型的一個副本,相當於prototype.__proto__ = Parent.prototype prototype.constructor = Child Child.prototype = prototype } prototype(Child,Parent) //必須執行這個函數,才能進行給子類型原型寫方法,順序調轉的話子類型原型會被重寫 Child.prototype.getName = function(){ console.log(this.name) }
優點:完美 缺點:用起來麻煩
class繼承
class Parent { constructor(name,age){ this.name = name this.age = age } showName(){ console.log(this.name); } } class Child extends Parent{ constructor(name,age,sex){ super(name,age) this.sex = sex } showSex(){ console.log(this.sex); } } let parent = new Parent(‘Jack‘,30) console.log(parent.name,parent.age); let child = new Child(‘Tom‘,12,‘男‘) console.log(child.name,child.age); child.showName() //Tom child.showSex() //男
js中7種繼承的實現和優缺點