寫在前面
繼承的簡介
繼承”是JavaScript面向對象設計的重要一環,愿你認真讀完本文,吃透繼承的概念。
繼承的核心
1. 繼承方式一:原型鏈
1.1 介紹
原型鏈是實現繼承最原始的模式,即通過prototype屬性實現繼承。
//父級-構造函數function Father() { this.fatherProp = true}//父級-原型屬性Father.prototype.getFatherValue = function() { return this.fatherProp}//子級-構造函數function Son() { this.sonProp = false}//子級-原型屬性:繼承父級//即__proto__指向父級的prototype//若不理解請閱讀《一張圖徹底KO原型鏈(prototype,__proto__》Son.prototype = new Father()//子級-添加原型方法Son.prototype.getSonValue = function() { return this.sonProp}//創建子級的實例對象var son = new Son()console.log(son.getFatherValue()) //true
1.2 解析:son實例對象是如何找到getFatherValue()方法的呢?
如果到最后都沒找到,會發生什么呢?
//一個不存在的方法console.log(son.getValue()) //ERROE:not a function
1.3 注意事項
重寫父級原型鏈的方法或者添加父級原型鏈不存在的方法,必須在父級原型鏈代碼之后。(這個很好理解,不放代碼演示了)
通過原型鏈實現繼承后,不能再使用字面量的方式創建原型對象,因為會覆蓋原型鏈。
//子級-原型屬性:繼承父級Son.prototype = new Father()//不能像下面這樣,這樣會使得上面的代碼無效//因為這相當于重新創建了一個原型對象Son.prototype = { getSonValue: function() { return this.sonProp }}
1.4 原型鏈實現繼承的弊端
世間萬事萬物都不可能十全而十美,原型鏈雖然強大,但也存在缺陷。
原型鏈中引用類型的屬性會被所有實例共享的,即所有實例對象使用的是同一份數據,會相互影響。
function Father() { this.arr = [1,2,3] } function Son() { } Son.prototype = new Father() var son1 = new Son() console.log(son1.arr) //1,2,3 var son2 = new Son() son2.arr.push(4) console.log(son2.arr) //1,2,3,4 console.log(son1.arr) //1,2,3,4
無法向父級構造函數傳參
2. 繼承方式二:借用構造函數
2.1 介紹
方式一中引用類型帶來的問題可借用構造函數的方式解決。其核心思想是:在子級構造函數中調用父級構造函數。
如何實現在一個構造函數中調用另一個函數?――call()和apply()
function Father() { this.arr = [1,2,3] } function Son() { //call的第一個函數是this指向的對象,即構造函數的實例對象 Father.call(this) /*上面代碼等同于下面這段代碼: (function() { this.arr = [1,2,3] }).call(this) */ } var son1 = new Son() console.log(son1.arr) //1,2,3 var son2 = new Son() son2.arr.push(4) console.log(son2.arr) //1,2,3,4 console.log(son1.arr) //1,2,3
//解決傳參問題:function Father(name) { this.name = name}function Son(name) { Father.call(this, name)}var son1 = new Son("小名")console.log(son1.name) //小名var son2 = new Son("一燈")console.log(son2.name) //一燈
2.2 借用構造函數的缺陷
這種方式是通過構造函數實現的,當然也把構造函數自身的問題帶過來了――破壞了復用性。因為每個實例都創建了一份副本。
3. 組合繼承
3.1 介紹
組合繼承 = 原型鏈 + 借用構造函數。取其長避其短:共享的用原型鏈,各自的借用構造函數
function Father(name) { this.name = name this.arr = [1,2,3]}Father.prototype.getName = function() { console.log(this.name)}function Son(name, age) { Father.call(this, name) this.age = age}Son.prototype = new Father()Son.prototype.constructor = SonSon.prototype.getAge = function() { console.log(this.age)}var son1 = new Son("小名", 23)son1.arr.push(4)console.log(son1.arr) //1,2,3,4son1.getName() //小名son1.getAge() //23var son2 = new Son("一燈", 24)console.log(son2.arr) //1,2,3son1.getName() //一燈son1.getAge() //24
3.2 解析
借用構造函數部分:
Father.call(this, name)――name來自Father
this.age = age; Son.prototype.constructor = Son――age來自Son
原型鏈部分:
Father.prototype.getName――getName方法來自Father.prototype
Son.prototype.getAge――getAge來自Son.prototype
后記
關于繼承的后三種方式馬上推出,期待你的點贊&關注!
以上所述是小編給大家介紹的js繼承方式詳解整合,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對武林網網站的支持!
新聞熱點
疑難解答