摘要:原型我們知道任何一個函數都存在一個屬性,他是個對象,這個對象我們就叫他原型對象這個原型對象本身也自帶兩個屬性和這個屬性是指向創建此對象的構造函數的引用,構造函數的實例化對象,也可以通過屬性來訪問構造它的那個函數這個屬性指向創建此對象的構造函
原型
我們知道任何一個函數都存在一個prototype屬性,他是個對象,這個對象 我們就叫他原型對象
這個原型對象本身也自帶兩個屬性:constructor 和 proto
constructor: 這個屬性是指向創建此對象的構造函數的引用,構造函數的實例化對象,也可以通過constuctor屬性來訪問構造它的那個函數_proto_: 這個屬性指向創建此對象的構造函數的prototype原型對象的引用
例子: //我的家族姓莫 function Parent(){ this.name = "mo" } //我家族是音樂世家 Parent.prototype.work = function(){ return "musicing" } //爸媽生了我 var me = new Parent() //我也要唱歌 console.log(me.work()) //=>musicing //爸爸媽媽又生了二胎 var myBrother = new Parent() //他也會唱歌 console.log(myBrother.work()) //=>musicing //證明我兩是否是親生的 console.log(me.work() === myBrother.work()) //=>true 解釋一波: me 和 myBrother 是構造函數Parent()new出來的的一個實例,me 和 myBrother 都有一個隱式屬性_proto_,引用Parent() 的prototype屬性來得到繼承原型鏈
在訪問 me 的 work 方法時,找不到, 就會順著_protp_屬性往上在構造函數的prototype找,找到了就停止,沒找到繼續往上到Object.prototype找,再沒找到就到null了,自然也找不到就只能返回undifined,這種鏈式的引用就是原型鏈,通過原型鏈實現繼承還是很方便的
萬一原型鏈斷鏈呢?原因:如果對 構造函數 或者 原型鏈 修改一些方法或者屬性的時候,導致函數的constructor不等于創建它的構造函數,那就會斷鏈
如果 先實例再通過 字面量添加或修改,那么后新定義的方法就對先繼承的方法或屬性就會不在生效,就會斷鏈,這是因為字面量來修改原型時,constructor發生了改變,也就是說該函數指向的創建該函數的構造函數發生了改變,字面量默認的constructor的值是Object(),所以為了避免斷鏈,盡量不要使用字面量重新賦值,修改
例子: //創建一個構造函數Car function Car(){ this.brand = "大奔"; } //大奔 80萬 Car.prototype.price = "80"; //我來買一個大奔 先實例 var benCar1 = new Car(); console.log(benCar1.price) //=>80 //我希望我的大奔 帶有翅膀的 能飛 Car.prototype = { hasWing: true, hasFlying: function(){ console.log("flying...") } } var benCar = new Car() (1) 正常情況下 console.log(benCar1.brand,benCar1.price,benCar1.hasWing,benCar1.hasFlying,benCar1.constructor) //=> 大奔 80 undefined undefined ? Car(){} (2)字面量添加屬性方法時 console.log(benCar.brand,benCar.price,benCar.hasWing,benCar.hasFlying,benCar.constructor) //=> 大奔 undefined true ? (){} ? Object() { [native code] }繼承的幾種方式
(1) 原型鏈繼承
原型鏈繼承是通過 new實例化構造函數 賦給子類的原型, 其實實例的子類本身是完全的空對象,所有的屬性方法都需要去原型鏈上找。
例子: function Grandpa(){ this.name = "mo" } Grandpa.prototype.work = function(){ return "musicing" } function Parent(){ } Parent.prototype = new Grandpa() var me = new Parent() console.log(me.work()) //=>musicing 我找啊找啊原來是Grandpa會musicing var myBrother = new Parent() console.log(myBrother.work()) //=>musicing console.log(me.work() === myBrother.work()) //=>true
(2) 構造函數繼承
構造函數繼承 通過apply去調用父類的構造函數,達到繼承父類的實例屬性,對,只能繼承屬性,要想繼承方法 采用寄生組合繼承
例子 function Grandpa(firstname){ this.name = "mo " + firstname } Grandpa.prototype.work = function(){ return "musicing" } function Parent(firstname){ Grandpa.apply(this, arguments) } Parent.prototype = new Grandpa() var me = new Parent("alice") console.log(me.work()) //=>musicing var myBrother = new Parent("bob") console.log(myBrother.work()) //=>musicing console.log(me.work() === myBrother.work()) //=>true console.log(me.name, myBrother.name,me.name === myBrother.name)//=>mo alice ,mo bob ,false
(3) 寄生組合繼承
寄生組合繼承是我們經常要用到的,組合了原型和構造函數,結合Object.create(obj),方法對傳入的對象進行淺拷貝,這樣可以實現對實例屬性和原型屬性分別進行繼承
淺拷貝:僅僅是指向被拷貝的內存地址,如果原地址中對象被改變了,那么淺拷貝出來的對象也會相應改變
例子: // 寄生組合繼承 function Grandpa(firstname){ this.name = "mo " + firstname } Grandpa.prototype.work = function(){ return "musicing" } function Parent(firstname){ Grandpa.apply(this, arguments) } // Parent.prototype = new Grandpa() //改成 Parent.prototype = Object.create(Grandpa.prototype); // Object.create()將父級對象的屬性和方法進行引用 Parent.prototype.constructor = Parent; //將該函數的construnctor指向parent構造函數 console.log(Parent.prototype) var me = new Parent("alice") var myBrother = new Parent("bob") console.log(me.work() === myBrother.work()) //=>true console.log(me.name, myBrother.name,me.name === myBrother.name)//=>mo alice ,mo bob ,false
好了,有時間還會補充...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/90456.html
摘要:只要沒有被覆蓋的話對象原型的屬性就能在所有的實例中找到,若整個原型鏈未找到則返回如何實現繼承構造繼承原型繼承實例繼承拷貝繼承原型機制或和方法去實現較簡單,建議使用構造函數與原型混合方式。 HTML相關問題 1.XHTML和HTML有什么區別 HTML是一種基本的WEB網頁設計語言,XHTML是一個基于XML的標記語言最主要的不同:XHTML 元素必須被正確地嵌套。XHTML 元素必須被...
摘要:只要沒有被覆蓋的話對象原型的屬性就能在所有的實例中找到,若整個原型鏈未找到則返回如何實現繼承構造繼承原型繼承實例繼承拷貝繼承原型機制或和方法去實現較簡單,建議使用構造函數與原型混合方式。 HTML相關問題 1.XHTML和HTML有什么區別 HTML是一種基本的WEB網頁設計語言,XHTML是一個基于XML的標記語言最主要的不同:XHTML 元素必須被正確地嵌套。XHTML 元素必須被...
摘要:只要沒有被覆蓋的話對象原型的屬性就能在所有的實例中找到,若整個原型鏈未找到則返回如何實現繼承構造繼承原型繼承實例繼承拷貝繼承原型機制或和方法去實現較簡單,建議使用構造函數與原型混合方式。 HTML相關問題 1.XHTML和HTML有什么區別 HTML是一種基本的WEB網頁設計語言,XHTML是一個基于XML的標記語言最主要的不同:XHTML 元素必須被正確地嵌套。XHTML 元素必須被...
摘要:就是這個原理直接將某個對象直接賦值給構造函數的原型。五寄生式繼承重點創建一個僅用于封裝繼承過程的函數,該函數在內部以某種方式來增強對象,最后返回構造函數。 一、原型鏈繼承 重點:利用原型讓一個引用類型繼承另外一個引用類型的屬性和方法。構造函數,原型,實例之間的關系:每個構造函數都有一個原型對象,原型對象包含一個指向構造函數的指針,而實例都包含一個指向原型對象的內部指針。 functio...
摘要:綜上所述有原型鏈繼承,構造函數繼承經典繼承,組合繼承,寄生繼承,寄生組合繼承五種方法,寄生組合式繼承,集寄生式繼承和組合繼承的優點于一身是實現基于類型繼承的最有效方法。 一、前言 繼承是面向對象(OOP)語言中的一個最為人津津樂道的概念。許多面對對象(OOP)語言都支持兩種繼承方式::接口繼承 和 實現繼承 。 接口繼承只繼承方法簽名,而實現繼承則繼承實際的方法。由于js中方法沒有簽名...
閱讀 2609·2021-11-17 17:00
閱讀 1864·2021-10-11 10:57
閱讀 3716·2021-09-09 11:33
閱讀 911·2021-09-09 09:33
閱讀 3550·2019-08-30 14:20
閱讀 3312·2019-08-29 11:25
閱讀 2796·2019-08-26 13:48
閱讀 734·2019-08-26 11:52