摘要:缺點(diǎn)方法都在構(gòu)造函數(shù)中定義,每次創(chuàng)建實(shí)例都會(huì)創(chuàng)建一遍方法組合繼承組合繼承融合原型鏈繼承和構(gòu)造函數(shù)的優(yōu)點(diǎn),是中最常用的繼承模式然而組合繼承也有一個(gè)缺點(diǎn),就是會(huì)調(diào)用兩次父構(gòu)造函數(shù)。
1.前言
本文完整代碼指路我的GitHub,歡迎star。js中的繼承方式有很多種,以下僅列出部分。
2.原型鏈繼承代碼如下:
function Parent() { this.name = "jchermy"; } Parent.prototype.getName = function() { console.log(this.name); } function Child() { } Child.prototype = new Parent(); var child1 = new Child(); console.log(child1.getName()); //jchermy
這樣看來貌似可以完美完成繼承,然后當(dāng)屬性換成引用類型時(shí),就會(huì)出現(xiàn)問題了,如下:
function Parent() { this.names = ["aa", "bb"]; //引用類型值 } function Child() { } Child.prototype = new Parent(); var child1 = new Child(); child1.names.push("cc"); console.log(child1.names); //["aa","bb","cc"] var child2 = new Child(); console.log(child2.names); //["aa","bb","cc"] child2.names.push("dd"); console.log(child1.names) //["aa", "bb", "cc", "dd"] console.log(child2.names);//["aa", "bb", "cc", "dd"] var p = new Parent(); console.log(p.names); //["aa", "bb"]
由此我們可以得出原型鏈繼承的缺點(diǎn):
引用類型的屬性被所有實(shí)例共享
在創(chuàng)建Child實(shí)例時(shí),不能向Parent傳參
2.借用構(gòu)造函數(shù)繼承function Parent() { this.names = ["aa", "bb"]; } function Child() { Parent.call(this); } var child1 = new Child(); child1.names.push("cc"); console.log(child1.names);//["aa", "bb", "cc"] var child2 = new Child(); console.log(child2.names);//["aa", "bb"] child2.names.push("dd"); console.log(child1.names); //["aa", "bb", "cc"] console.log(child2.names); //["aa", "bb", "dd"] var p = new Parent(); p.names; //["aa", "bb"]
可以看出,借用構(gòu)造函數(shù)繼承避免了一下原型鏈繼承的問題,主要體現(xiàn)在:
避免了引用類型的屬性被所有實(shí)例共享
可以在Child中向Parent傳參
然而,借用構(gòu)造函數(shù)繼承也有缺點(diǎn)。
function Parent(name) { this.name = "parent "+name; } function Child(name) { this.name = "child"+name; Parent.call(this, name); } var child1 = new Child("hemin"); console.log(chil1.name); //"parent hemin" var child2 = new Child("aa"); console.log(child2.name); //"parent aa"
缺點(diǎn):方法都在構(gòu)造函數(shù)中定義,每次創(chuàng)建實(shí)例都會(huì)創(chuàng)建一遍方法
3.組合繼承組合繼承融合原型鏈繼承和構(gòu)造函數(shù)的優(yōu)點(diǎn),是JavaScript中最常用的繼承模式
function Parent(name) { this.name = name; this.colors = ["red", "blue"]; } Parent.prototype.getName = function() { console.log(this.name); } function Child(name, age) { Parent.call(this, name); this.age = age; } Child.prototype = new Parent(); Child.prototype.constructor = Child; var child1 = new Child("aa", 18); child1.colors.push("black"); child1.name; //"aa" child1.age; //18 child1.colors; //["red", "blue","black"] var child2 = new Child("bb", 20); child2.name; //"bb" child2.age; //20 child2.colors; //["red", "blue"]
然而組合繼承也有一個(gè)缺點(diǎn),就是會(huì)調(diào)用兩次父構(gòu)造函數(shù)。
如下:
Child.prototype = new Parent(); var child1 = new Child("aa", "18");
所以,在這個(gè)例子中,如果我們打印 child1 對(duì)象,我們會(huì)發(fā)現(xiàn) Child.prototype 和 child1 都有一個(gè)屬性為colors,屬性值為["red", "blue"]。
這個(gè)問題我們?cè)谙旅嬖儆懻摗?/p> 4.原型式繼承
function createObj(o) { function F() {} F.prototype = o; return new F(); } var person = { name: "jchermy", friends: ["aa", "bb"] } var person1 = createObj(person); var person2 = createObj(person); //注意:修改person1.name的值,person2.name的值并未發(fā)生改變, //并不是因?yàn)閜erson1和person2有獨(dú)立的 name 值,而是因?yàn)閜erson1.name = "person1",給person1添加了 name 值,并非修改了原型上的 name 值。 person1.name = "xiaomi"; console.log(person2.name); //"jchermy" person2.friends.push("cc"); console.log(person1.friends); //["aa", "bb", "cc"]
缺點(diǎn):包含引用類型的屬性值始終會(huì)共享相應(yīng)的值,與原型鏈繼承一樣
5.寄生式繼承創(chuàng)建一個(gè)僅用于封裝繼承過程的函數(shù),該函數(shù)在內(nèi)部以某種形式做增強(qiáng)對(duì)象,最后返回對(duì)象
function createObj(o) { var clone = Object.create(o); clone.sayName = function () { console.log("hi"); } return clone; } var person = { name: "jchermy", friends: ["aa", "bb"] }; var person1 = createObj(person); var person2 = createObj(person); person1.name = "xiaomi"; console.log(person1.name); //"xiaomi" console.log(person2.name); //"jchermy" person1.friends.push("xxx"); console.log(person1.friends); // ["aa", "bb", "xxx"] console.log(person2.friends); // ["aa", "bb", "xxx"]
缺點(diǎn):
跟借用構(gòu)造函數(shù)模式一樣,每次創(chuàng)建對(duì)象都會(huì)創(chuàng)建一遍方法
包含引用類型的屬性值始終會(huì)共享相應(yīng)的值
6.寄生組合式繼承還記得組合繼承中提到的那些問題嗎,那么我們?cè)撊绾尉媲缶苊膺@一次重復(fù)調(diào)用呢?
如果我們不使用 Child.prototype = new Parent() ,而是間接的讓 Child.prototype 訪問到 Parent.prototype 呢?可以這樣實(shí)現(xiàn):
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; } //關(guān)鍵的三步 var F = function(){}; F.prototype = Parent.prototype; Child.prototype = new F(); Child.prototype.constructor = Child; var child1 = new Child("xiaomi", 18); var child2 = new Child2("aa", 24); console.log(child1.name); //xiaomi console.log(child2.name); //aa child1.colors.push("black"); child1.colors; //["red", "blue", "green", "black"] child2.colors; //["red", "blue", "green"];
這種方式的高效率體現(xiàn)它只調(diào)用了一次 Parent 構(gòu)造函數(shù),并且因此避免了在 Parent.prototype 上面創(chuàng)建不必要的、多余的屬性。與此同時(shí),原型鏈還能保持不變;因此,還能夠正常使用 instanceof 和 isPrototypeOf。開發(fā)人員普遍認(rèn)為寄生組合式繼承是引用類型最理想的繼承范式。7.結(jié)語
如果文章對(duì)你有幫助的話,歡迎點(diǎn)贊和收藏!!有錯(cuò)誤和不合理的地方歡迎大家指正!GitHub給個(gè)star就最好啦!=(//▽//)感謝大家~
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/95526.html
摘要:中繼承比較復(fù)雜,坑比較多,最近有點(diǎn)時(shí)間整理下,記錄下來。的繼承實(shí)現(xiàn)方式大概分類如下的兩大類,每一種實(shí)現(xiàn)都有自己的有點(diǎn)和缺點(diǎn),根據(jù)場(chǎng)景選擇吧通過修改原型鏈來來實(shí)現(xiàn)繼承通過復(fù)制父類來來實(shí)現(xiàn)繼承為了理解繼承的原型鏈的變化,我畫了原型鏈圖。 JS 中繼承比較復(fù)雜,坑比較多,最近有點(diǎn)時(shí)間整理下,記錄下來。 JS 的繼承實(shí)現(xiàn)方式大概分類如下的兩大類,每一種實(shí)現(xiàn)都有自己的有點(diǎn)和缺點(diǎn),根據(jù)場(chǎng)景選擇吧 ...
摘要:設(shè)計(jì)模式是以面向?qū)ο缶幊虨榛A(chǔ)的,的面向?qū)ο缶幊毯蛡鹘y(tǒng)的的面向?qū)ο缶幊逃行┎顒e,這讓我一開始接觸的時(shí)候感到十分痛苦,但是這只能靠自己慢慢積累慢慢思考。想繼續(xù)了解設(shè)計(jì)模式必須要先搞懂面向?qū)ο缶幊蹋駝t只會(huì)讓你自己更痛苦。 JavaScript 中的構(gòu)造函數(shù) 學(xué)習(xí)總結(jié)。知識(shí)只有分享才有存在的意義。 是時(shí)候替換你的 for 循環(huán)大法了~ 《小分享》JavaScript中數(shù)組的那些迭代方法~ ...
摘要:參與任何數(shù)值計(jì)算的結(jié)構(gòu)都是,而且。。面向人類的理性事物,而不是機(jī)器信號(hào)。達(dá)到無刷新效果。的工作原理總是指向一個(gè)對(duì)象,具體是運(yùn)行時(shí)基于函數(shù)的執(zhí)行環(huán)境動(dòng)態(tài)綁定的,而非函數(shù)被聲明時(shí)的環(huán)境。原型對(duì)象上有一個(gè)屬性,該屬性指向的就是構(gòu)造函數(shù)。 1.JS面向?qū)ο蟮睦斫?面向?qū)ο蟮娜筇攸c(diǎn):繼承、封裝、多態(tài) 1、JS中通過prototype實(shí)現(xiàn)原型繼承 2、JS對(duì)象可以通過對(duì)象冒充,實(shí)現(xiàn)多重繼承, 3...
摘要:忍者級(jí)別的函數(shù)操作對(duì)于什么是匿名函數(shù),這里就不做過多介紹了。我們需要知道的是,對(duì)于而言,匿名函數(shù)是一個(gè)很重要且具有邏輯性的特性。通常,匿名函數(shù)的使用情況是創(chuàng)建一個(gè)供以后使用的函數(shù)。 JS 中的遞歸 遞歸, 遞歸基礎(chǔ), 斐波那契數(shù)列, 使用遞歸方式深拷貝, 自定義事件添加 這一次,徹底弄懂 JavaScript 執(zhí)行機(jī)制 本文的目的就是要保證你徹底弄懂javascript的執(zhí)行機(jī)制,如果...
摘要:系列種優(yōu)化頁面加載速度的方法隨筆分類中個(gè)最重要的技術(shù)點(diǎn)常用整理網(wǎng)頁性能管理詳解離線緩存簡(jiǎn)介系列編寫高性能有趣的原生數(shù)組函數(shù)數(shù)據(jù)訪問性能優(yōu)化方案實(shí)現(xiàn)的大排序算法一怪對(duì)象常用方法函數(shù)收集數(shù)組的操作面向?qū)ο蠛驮屠^承中關(guān)鍵詞的優(yōu)雅解釋淺談系列 H5系列 10種優(yōu)化頁面加載速度的方法 隨筆分類 - HTML5 HTML5中40個(gè)最重要的技術(shù)點(diǎn) 常用meta整理 網(wǎng)頁性能管理詳解 HTML5 ...
閱讀 2345·2021-11-23 09:51
閱讀 1999·2021-10-14 09:43
閱讀 2760·2021-09-27 13:35
閱讀 1144·2021-09-22 15:54
閱讀 2495·2021-09-13 10:36
閱讀 3785·2019-08-30 15:56
閱讀 3404·2019-08-30 14:09
閱讀 1711·2019-08-30 12:57