摘要:中的繼承概述原型鏈可以用來實現(xiàn)共享,構(gòu)造函數(shù)可以讓對象擁有自己的屬性,兩者結(jié)合的組合的組合繼承便是最常用的繼承方式。不易理解的地方的屬性在實例中而不在構(gòu)造函數(shù)中的屬性在中而不在構(gòu)造函數(shù)中。
1 前言
我試圖用簡單、清晰、專業(yè)的方式講清楚js繼承這么一個有點復雜的問題
2 繼承的精髓 2.1 為什么要繼承?因為需要復用
2.2需要復用什么?該如何復用?通過復用我們可以實現(xiàn)共享。
從對象的角度來說,我們不想重復寫同一段邏輯,所以邏輯需要復用;但是我們不希望一個對象掌管的變量被其它對象修改。所以變量不能共享。也就是要共享函數(shù),不共享屬性。
3 js中的繼承 3.1 概述原型鏈可以用來實現(xiàn)共享,構(gòu)造函數(shù)可以讓對象擁有自己的屬性,兩者結(jié)合的組合的組合繼承便是最常用的繼承方式。
組合繼承中有一個弊端,通過簡單的改進,寄生組合式繼承可以實現(xiàn)最有效的繼承。接下來將展開講解組合繼承和寄生組合式繼承。
3.2 預備知識如果已經(jīng)了解了這些知識,可以直接跳過
function Person () { } Person.prototype.name = "Nicholas"; Person.prototype.age = 29; Person.prototype.job="Software Engineer"; Person.prototype.sayName=function () { console.log(this.name); }; var person1=new Person(); person1.sayName();//Nicholas
構(gòu)造函數(shù)(Person)可以用來創(chuàng)建實例(person1),創(chuàng)建的實例和構(gòu)造函數(shù)共同指向一個原型(Person.prototype),原型的構(gòu)造器又指向了構(gòu)造函數(shù)。
如果沒有指定原型,則默認的原型為Object.prototype。
new操作符具體干了什么呢?
創(chuàng)建一個空對象,并且 this 變量引用該對象,同時還繼承了該函數(shù)的原型。var obj = {};
屬性和方法被加入到 this 引用的對象中。obj.__proto__ = Base.prototype; (圖示中用[[Prorotype]]代表__proto__)
新創(chuàng)建的對象由 this 所引用,并且最后隱式的返回 this 。Base.call(obj);
屏蔽:
//...上面的代碼,此處省略 var person2=new Person(); person1.name="Mike"; person1.sayName();//Mike person2.sayName();//Nicholas
屬性值沿著原型鏈,遵循就近原則。就近的屬性值會屏蔽上層原型鏈的屬性值
動態(tài)追加而非斷開:
誤區(qū):javaScript高級程序設計第三版 中指出了 修改原型時 這樣一種斷開情景
function Person () { } var friend=new Person(); Person.prototype={ constructor:Person, name:"Nicholas", age:29, job:"Software Engineer", sayName:function () { console.log(this.name); } } friend.sayName();//error
friend的原型丟失了,和它斷開了聯(lián)系。
其實現(xiàn)在已經(jīng)有所改進,運行friend.sayName();,應該輸出為:Nicholas,當修改原型時,語言的設計意圖是什么?如果你是語言的設計者到底應該為何種輸出?
我認為最好的效果是確保其穩(wěn)妥性的同時,又不失靈活是最佳的,在這個例子中,創(chuàng)建完原型關(guān)系后又想追加原型中的屬性,我希望他能夠追加成功,因此,希望它輸出為:Nicholas。
但是,我不希望原型中的屬性隨意修改,先開始的時候我給他賦予了值,也定義了相應的方法使用這個值,如果這個值在后期隨意修改的話,使用這個方法的時候會覺得不知所措。
所以我希望的涉及是原型屬性值可以追加但定義后值不能隨意修改,如下:
function Person () { } Person.prototype.name = "Greg"; Person.prototype.age = 24; Person.prototype.job="Doctor"; var friend=new Person(); Person.prototype={ constructor:Person, name:"Nicholas", age:29, job:"Software Engineer", sayName:function () { console.log(this.name); } } friend.sayName();//Greg
打印friend.__proto__:
Object {name: "Greg", age: 24, job: "Doctor"} age:24 job:"Doctor" name:"Greg" sayName:function()3.2.3 總結(jié)
橫向上,每個原型的屬性 在原型本身被修改時 只是動態(tài)追加而不會修改原值;縱向上,原型鏈繼承遵循就近原則。
3.3 組合繼承讓一個構(gòu)造函數(shù)A的原型為另一個構(gòu)造函數(shù)B的實例,便形成了A繼承B的原型鏈。
function SuperType() { this.property=true; } SuperType.prototype.getSuperValue=function () { return this.property; }; function SubType() { this.subproperty=false; }; SubType.prototype=new SuperType(); SubType.prototype.getSubValue=function () { return this.subproperty; } var instance=new SubType();
不易理解的地方:subproperty的屬性在實例中而不在SubType構(gòu)造函數(shù)中;property的屬性在 SubType.prototype中而不在SuperType構(gòu)造函數(shù)中。
講解:subproperty和property都是實例屬性,在哪里創(chuàng)建了實例就出現(xiàn)在哪里,
優(yōu)勢:函數(shù)共享
缺陷:原型鏈體現(xiàn)出了共享的特性,當一個實例改變了其從原型那里繼承來的引用屬性值時,其它繼承自這個原型屬性的值都將被改變。
function SuperType() { this.colors=["red","blue","green"]; } function SubType() { }; SubType.prototype=new SuperType(); var instance1=new SubType(); instance1.colors.push("black"); console.log(instance1.colors);//["red", "blue", "green", "black"] var instance2=new SubType(); console.log(instance2.colors);//["red", "blue", "green", "black"]
function SuperType(name) { this.name=name; } function SubType() { SuperType.call(this,"Nicholas"); this.age=29; } var instance=new SubType(); console.log(instance.name+" "+instance.age);//Nicholas 29
構(gòu)造函數(shù)每個實例的屬性都借助構(gòu)造函數(shù)自己生成
優(yōu)勢:每個實例屬性各自獨立
缺陷:無法共享函數(shù)
組合繼承結(jié)合了原型鏈繼承和構(gòu)造函數(shù)繼承的優(yōu)勢:
function SuperType(name) { this.name=name; this.colors=["red","blue","green"] } SuperType.prototype.sayName=function () { console.log(this.name); } function SubType(name,age) { SuperType.call(this,name); this.age=age; } SubType.prototype=new SuperType(); SubType.prototype.sayAge=function () { console.log(this.age); } var instance1=new SubType("Nicholas",29); instance1.colors.push("black"); console.log(instance1.colors); instance1.sayName(); instance1.sayAge(); var instance2=new SubType("Greg",27); console.log(instance2.colors); instance2.sayName(); instance2.sayAge();3.4 寄生組合式繼承
組合繼承雖然實現(xiàn)了需求:共享函數(shù),但不共享屬性,可是它是有不足之處:我們在獨立屬性時只是希望實例有各自的屬性就好了,不需要原型(SubType.prototype)中也存在屬性,這就多余了。
SubType.prototype存在屬性是因為它對SuperType做了實例化繼承,我們將實例話繼承換成前拷貝繼承便可以解決問題:
//將組合繼承中的實例化繼承: //SubType.prototype=new SuperType(); //改為淺拷貝繼承: function inheritPrototype(subType,superType){ var prototype=Object.create(superType.prototype);//創(chuàng)建對象 prototype.constructor=subType; subType.prototype=prototype; } inheritPrototype(SubType,SuperType);
Object.create()代碼說明:
function Object.create(o){ function F() {}; F.prototype=o; return new F(); }參考
javascript高級程序設計 第三版
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/80065.html
摘要:在本節(jié)中,我們將看到一些最流行和最常用的庫,用于機器學習和深度學習是用于數(shù)據(jù)挖掘,分析和機器學習的最流行的庫。愿碼提示網(wǎng)址是一個基于的框架,用于使用多個或進行有效的機器學習和深度學習。 showImg(https://segmentfault.com/img/remote/1460000018961827?w=999&h=562); 來源 | 愿碼(ChainDesk.CN)內(nèi)容編輯...
摘要:接下來本清單還列舉了對于接入過濾與防攻擊使用合適的方法并且對用戶輸入進行有效校驗避免關(guān)鍵資源外泄設置合理的響應頭等等內(nèi)容。該論文的主要論點是,沒有任何一項技術(shù)或方法可以能讓軟件工程的生產(chǎn)力在十年內(nèi)提高十倍。 推薦 1. Styled-Components 實戰(zhàn) https://hackernoon.com/styled... Styled-Components 是由 Max Stoib...
摘要:接下來本清單還列舉了對于接入過濾與防攻擊使用合適的方法并且對用戶輸入進行有效校驗避免關(guān)鍵資源外泄設置合理的響應頭等等內(nèi)容。該論文的主要論點是,沒有任何一項技術(shù)或方法可以能讓軟件工程的生產(chǎn)力在十年內(nèi)提高十倍。 推薦 1. Styled-Components 實戰(zhàn) https://hackernoon.com/styled... Styled-Components 是由 Max Stoib...
摘要:從零開始單排學設計模式的國服排位之旅,今天正式開啟目前段位定級賽這篇文章來總結(jié)下類圖,本來不打算講類圖的,因為我在學習設計模式的時候,一遇到有關(guān)的就會自動忽略,一看感覺就很復雜。關(guān)聯(lián)關(guān)系用實現(xiàn)箭頭來表示。 閱讀本文大概需要 3.5 分鐘。 本篇是設計模式系列的開篇,雖然之前也寫過相應的文章,但是因為種種原因后來斷掉了,而且發(fā)現(xiàn)之前寫的內(nèi)容也很渣,不夠系統(tǒng)。 所以現(xiàn)在打算重寫,加上距離現(xiàn)...
閱讀 2799·2021-11-24 09:39
閱讀 2558·2021-11-23 09:51
閱讀 1877·2021-11-17 09:33
閱讀 1760·2021-10-22 09:54
閱讀 1884·2021-08-16 11:00
閱讀 3440·2019-08-30 15:53
閱讀 1743·2019-08-30 13:19
閱讀 2916·2019-08-30 12:49