日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

js继承之借用构造函数继承

發布時間:2024/6/21 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 js继承之借用构造函数继承 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2018.5.27

今天本人又在查關于繼承的問題,重新溫習了一遍書,發現之前舉的例子實際上不太清晰,故做調整。


?

我的上一篇文章介紹了,原型鏈繼承模式。原型鏈繼承雖然很強大,但是單純的原型鏈模式并不能很好地實現繼承。

一、原型鏈的缺點

1.1 單純的原型鏈繼承最大的一個缺點,在于對原型中引用類型值的誤修改。

  先看一個例子:

   //父類:人function Person () {this.head = '腦袋瓜子';}//子類:學生,繼承了“人”這個類function Student(studentID) {this.studentID = studentID;}Student.prototype = new Person();var stu1 = new Student(1001);console.log(stu1.head); //腦袋瓜子 stu1.head = '聰明的腦袋瓜子';console.log(stu1.head); //聰明的腦袋瓜子var stu2 = new Student(1002);console.log(stu2.head); //腦袋瓜子

?

  以上例子,我們通過重寫 Student.prototype 的值為 Person 類的一個實例,實現了 Student 類對 Person 類的繼承。所以 ,stu1 能訪問到父類 Person 上定義的 head 屬性,打印值為“腦袋瓜子”。我們知道,所有的 Student 實例都共享著原型對象上的屬性。那么,如果我在 stu1 上改變了 head 屬性值,是不是會影響原型對象上的 head 值呢?看我上面的代碼就知道,肯定是不會。stu1 的 head 值確實是改變了,但是我重新實例化的對象 stu2 的 head 值仍舊不變。

  這是因為,當實例中存在和原型對象上同名的屬性時,會自動屏蔽原型對象上的同名屬性。stu1.head = "聰明的腦袋瓜子" 實際上只是給 stu1 添加了一個本地屬性 head 并設置了相關值。所以當我們打印 stu1.head 時,訪問的是該實例的本地屬性,而不是其原型對象上的 head 屬性(它因和本地屬性名同名已經被屏蔽了)。

?

  剛才我們討論的這個 head 屬性是一個基本類型的值,可如果它是一個引用類型呢?這其中又會有一堆小九九。

  其實原型對象上任何類型的值,都不會被實例所重寫/覆蓋。在實例上設置與原型對象上同名屬性的值,只會在實例上創建一個同名的本地屬性。

  但是,原型對象上引用類型的值可以通過實例進行修改,致使所有實例共享著的該引用類型的值也會隨之改變。

  再看下面這個例子:

//父類:人function Person () {this.head = '腦袋瓜子';this.emotion = ['喜', '怒', '哀', '樂']; //人都有喜怒哀樂 }//子類:學生,繼承了“人”這個類function Student(studentID) {this.studentID = studentID;}Student.prototype = new Person();var stu1 = new Student(1001);console.log(stu1.emotion); //['喜', '怒', '哀', '樂'] stu1.emotion.push('愁');console.log(stu1.emotion); //["喜", "怒", "哀", "樂", "愁"]var stu2 = new Student(1002);console.log(stu2.emotion); //["喜", "怒", "哀", "樂", "愁"]

?

  我們在剛才的 Person 類中又添加了一個 emotion 情緒屬性,人都有喜怒哀樂嘛。尤其需要注意的是,這是一個引用類型的值。這時,stu1 認為他還很“愁”,所以就通過 stu1.emotion.push ( ) 方法在原來的基礎上增加了一項情緒,嗯,打印出來“喜怒哀樂愁”,沒毛病。可是 stu2 是個樂天派,他咋也跟著一起愁了呢?!肯定不對嘛~

  這就是單純的原型鏈繼承的缺點,如果一個實例不小心修改了原型對象上引用類型的值,會導致其它實例也跟著受影響。

  因此,我們得出結論,原型上任何類型的屬性值都不會通過實例被重寫,但是引用類型的屬性值會受到實例的影響而修改。

1.2 原型鏈不能實現子類向父類中傳參。這里就不細說了。

?

二、借用構造函數

2.1 實現原理

  在解決原型對象中包含引用類型值所帶來問題的過程中,開發人員開始使用一種叫做借用構造函數的技術。實現原理是,在子類的構造函數中,通過 apply ( ) 或 call ( )的形式,調用父類構造函數,以實現繼承。

//父類:人function Person () {this.head = '腦袋瓜子';this.emotion = ['喜', '怒', '哀', '樂']; //人都有喜怒哀樂 }//子類:學生,繼承了“人”這個類function Student(studentID) {this.studentID = studentID;Person.call(this);}//Student.prototype = new Person();var stu1 = new Student(1001);console.log(stu1.emotion); //['喜', '怒', '哀', '樂'] stu1.emotion.push('愁');console.log(stu1.emotion); //["喜", "怒", "哀", "樂", "愁"]var stu2 = new Student(1002);console.log(stu2.emotion); //["喜", "怒", "哀", "樂"]

?

  細心的同學可能已經發現了,該例子與上面的例子非常相似,只是去掉了之前通過 prototype 繼承的方法,而采用了 Person.call (this) 的形式實現繼承。別忘了,函數只不過是一段可以在特定作用域執行代碼的特殊對象,我們可以通過 call 方法指定函數的作用域。

  (題外話:也許有的同學對 this 的指向還不完全清楚,我是這么理解的:誰調用它,它就指向誰。)

  在 stu1 = new Student ( ) 構造函數時,是 stu1 調用 Student 方法,所以其內部 this 的值指向的是 stu1, 所以 Person.call (?this?) 就相當于Person.call (?stu1?),就相當于 stu1.Person( )。最后,stu1 去調用 Person 方法時,Person 內部的 this 指向就指向了 stu1。那么Person 內部this 上的所有屬性和方法,都被拷貝到了 stu1 上。stu2 也是同理,所以其實是,每個實例都具有自己的 emotion 屬性副本。他們互不影響。說到這里,大家應該清楚一點點了吧。

  總之,在子類函數中,通過call ( ) 方法調用父類函數后,子類實例 stu1, 可以訪問到 Student 構造函數和 Person 構造函數里的所有屬性和方法。這樣就實現了子類向父類的繼承,而且還解決了原型對象上對引用類型值的誤修改操作。

?

2.2 缺點

  這種形式的繼承,每個子類實例都會拷貝一份父類構造函數中的方法,作為實例自己的方法,比如 eat()。這樣做,有幾個缺點:

  1. 每個實例都拷貝一份,占用內存大,尤其是方法過多的時候。(函數復用又無從談起了,本來我們用 prototype 就是解決復用問題的)

  2. 方法都作為了實例自己的方法,當需求改變,要改動其中的一個方法時,之前所有的實例,他們的該方法都不能及時作出更新。只有后面的實例才能訪問到新方法。

//父類:人function Person () {this.head = '腦袋瓜子';this.emotion = ['喜', '怒', '哀', '樂']; //人都有喜怒哀樂this.eat = function () {console.log('吃吃喝喝');}this.sleep = function () {console.log('睡覺');}this.run = function () {console.log('快跑');}}?

  所以,無論是單獨使用原型鏈繼承還是借用構造函數繼承都有自己很大的缺點,最好的辦法是,將兩者結合一起使用,發揮各自的優勢。我將在下一篇文章作出解釋。js 繼承之組合繼承

?

如果你覺得文章解決了你的疑惑的話,還請賞我一個推薦哦~ ?:)

作者不才,文中若有錯誤,望請指正,避免誤人子弟。

文章內容全都參考于《JAVASCRIPT 高級程序設計》)

?

轉載于:https://www.cnblogs.com/sarahwang/p/6879161.html

總結

以上是生活随笔為你收集整理的js继承之借用构造函数继承的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。