摘要:通過新增方法規(guī)范了原型式繼承。適用場景在沒有必要興師動眾地創(chuàng)建構(gòu)造函數(shù),而只想讓一個對象與另外一個對象保持類似的情況下,原型式繼承是完全可以勝任的。在主要考慮對象而不是自定義類型和構(gòu)造函數(shù)的情況下,寄生式繼承也是一種有用的模式。
--
前言:最近在細讀Javascript高級程序設(shè)計,對于我而言,中文版,書中很多地方翻譯的差強人意,所以用自己所理解的,嘗試解讀下。如有紕漏或錯誤,會非常感謝您的指出。文中絕大部分內(nèi)容引用自《JavaScript高級程序設(shè)計第三版》。
道格拉斯 克勞克福德在2006年寫了一篇文章,題為Prototypal Inhertitance in JavaScript(JavaScript中的原型式繼承)。
在這篇文章中,他介紹了一種實現(xiàn)繼承的方法,這種方法并沒有使用嚴格意義上的構(gòu)造函數(shù)。
他的想法是借助原型可以基于已有的對象創(chuàng)建新對象,同時還不必因此創(chuàng)建自定義類型。
為了達到這個目的,他給出了如下函數(shù)。
function object(o) { function F(){}; F.prototype = o; return new F(); }
在object()函數(shù)內(nèi)部,先創(chuàng)建一個臨時性的構(gòu)造函數(shù),然后將傳入的對象作為這個構(gòu)造函數(shù)的原型,最后返回了這個臨時類型的一個新實例對象。
從本質(zhì)上講,object()對傳入的對象執(zhí)行了一次淺復制。
function object(o){ function F(){}; F.prototype = o; return new F(); } var person = { name: "Shaw", friends: ["Sharon", "Sandy", "Van"] } var person1 = object(person); /* person1 = function object(person){ function F(){}; F.prototype = person1; return new F(); }() person1 = function object({ name: "Shaw", friends: ["Sharon", "Sandy", "Van"] }){ function F(){}; F.prototype = { name: "Shaw", friends: ["Sharon", "Sandy", "Van"] } return { } } person1 = { }; {}.__proto__ = { name: "Shaw", friends: ["Sharon", "Sandy", "Van"] } */ person1.name = "Roc"; person1.friends.push("Roster"); var person2 = object(person); person2.name = "Linda"; person2.friends.push("Jobs"); console.log(person.friends); //["Sharon", "Sandy", "Van", "Roster", "Jobs"] console.log(person1.friends); //["Sharon", "Sandy", "Van", "Roster", "Jobs"] console.log(person2.friends); //["Sharon", "Sandy", "Van", "Roster", "Jobs"]
克羅克福德主張的這種原型式繼承,要求你必須有一個對象可以作為另一個對象的基礎(chǔ)。
如果有這么一個對象的話,可以把它傳給object()函數(shù),然后再根據(jù)具體需求對得到的對象加以修改即可。
ECMAscript5通過新增Object.create()方法規(guī)范了原型式繼承。
這個方法接收兩個參數(shù): 一個用作新對象原型的對象和(可選的)一個為新對象定義額外屬性的對象。
在傳入一個參數(shù)的情況下,Object.create()與object()方法的行為相同。
var person = { name: "Shaw", friends: ["Sharon", "Sandy", "Van"] } var person1 = Object.create(person); person1.name = "Roc"; person1.friends.push("Roster"); var person2 = Object.create(person); person2.name = "Linda"; person2.friends.push("Messi"); console.log(person.friends); //["Sharon", "Sandy", "Van", "Roster", "Messi"] console.log(person1.friends); //["Sharon", "Sandy", "Van", "Roster", "Messi"] console.log(person2.friends); //["Sharon", "Sandy", "Van", "Roster", "Messi"]
Object.create()方法的第二個參數(shù)與Object.defienProperties()方法的第二個參數(shù)格式相同:
每個屬性都是通過自己的描述符定義的。
以這種方式指定的任何屬性都會覆蓋原型對象上的同名屬性。
var person = { name: "Shaw", friends: ["Sharon", "Sandy", "Selina"] } var person1 = Object.create(person, { name: { value: "Roc" } }) console.log(person1.name); //"Roc"
支持Object.create()方法的瀏覽器有IE9+, Firefox 4+, Opera 12+ 和 Chrome。
適用場景:
在沒有必要興師動眾地創(chuàng)建構(gòu)造函數(shù),而只想讓一個對象與另外一個對象保持類似的情況下,原型式繼承是完全可以勝任的。
千萬要記住,包含引用類型值的屬性始終都會共享相應(yīng)的值,就像使用原型模式一樣。
寄生式繼承寄生式(parasitic)繼承是與原型式繼承緊密相關(guān)的一種思路,并且也是由大神克勞克福推而廣之的。
寄生式繼承的思路與寄生構(gòu)造函數(shù)和工廠模式類似。
創(chuàng)建一個僅用于封裝繼承過程的函數(shù),該函數(shù)在內(nèi)部以某種方式來增強對象,最后再像真地是它做了所有工作一樣返回對象。
function object(o){ function F(){}; F.prototype = o; return new F(); } function createAnother(original) { var clone = object(original); //通過調(diào)用函數(shù)創(chuàng)建一個新對象 clone.sayHi = function(){ //以某種方式來增強這個對象 console.log("hi"); } return clone; //返回這個對象 }
在這個例子中, createAnother()函數(shù)接收了換一個參數(shù),也就是將要作為新對象基礎(chǔ)的對象。
然后,把這個對象參數(shù)(original)傳遞給object()函數(shù), 將返回的結(jié)果賦值給clone。
再為clone對象添加一個新方法sayHi(),最后返回clone對象。
可以像下面這樣來使用createAnother()函數(shù):
function object(o){ function F(){}; F.prototype = o; return new F(); } function createAnother(original) { var clone = object(original); //通過調(diào)用函數(shù)創(chuàng)建一個新對象 clone.sayHi = function(){ //以某種方式來增強這個對象 console.log("hi"); } return clone; //返回這個對象 } var person = { name: "Shaw", friends: ["Sandy", "Sharon", "Van"] } var anotherPerson = createAnother(person); anotherPerson.sayHi(); //"hi"
這個例子中的代碼基于person返回一個新對象——anotherPerson。新對象不僅具有person的所有屬性和方法,而且還有還有自己的sayHi()方法。
在主要考慮對象而不是自定義類型和構(gòu)造函數(shù)的情況下,寄生式繼承也是一種有用的模式。
前面示范繼承模式時使用的object()函數(shù)不是必需的,任何能夠返回新對象的函數(shù)都適用于此模式。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/98656.html
摘要:寄生式繼承的思路與寄生構(gòu)造函數(shù)和工廠模式類似,即創(chuàng)建一個僅用于封裝繼承過程的函數(shù),該函數(shù)在內(nèi)部已某種方式來增強對象,最后再像真的是它做了所有工作一樣返回對象。 這篇本來應(yīng)該是作為寫JS 面向?qū)ο蟮那白啵皇亲鳛椤秊avascript高級程序設(shè)計》繼承一章的筆記 原型鏈 code 實現(xiàn) function SuperType() { this.colors = [red,blu...
摘要:除此之外,在超類型的原型中定義的方法,對子類型而言也是不可兼得,結(jié)果所有類型都只能用構(gòu)造函數(shù)模式。創(chuàng)建對象增強對象指定對象繼承屬性這個例子的高效率體現(xiàn)在它只調(diào)用了一次構(gòu)造函數(shù)。 1、原型鏈 原型鏈的基本思想是利用原型讓一個引用類型繼承另一個引用類型的屬性和方法。構(gòu)造函數(shù)、原型和實例的關(guān)系:每個構(gòu)造函數(shù)都有一個原型對象;原型對象都包含著一個指向構(gòu)造函數(shù)的指針;實例都包含一個指向原型對象的...
摘要:創(chuàng)建自定義的構(gòu)造函數(shù)之后,其原型對象只會取得屬性,其他方法都是從繼承來的。優(yōu)缺點寄生式繼承在主要考慮對象而不是創(chuàng)建自定義類型和構(gòu)造函數(shù)時,是十分有用的。 原文鏈接:https://kongchenglc.coding.me... 1.原型鏈 ??js的繼承機制不同于傳統(tǒng)的面向?qū)ο笳Z言,采用原型鏈實現(xiàn)繼承,基本思想是利用原型讓一個引用類型繼承另一個引用類型的屬性和方法。理解原型鏈必須先理...
摘要:組合繼承最大的問題就是無論在什么情況下,都會調(diào)用兩次超類型構(gòu)造函數(shù)一次是在創(chuàng)建子類型原型的時候。好在,我們已經(jīng)找到了解決這個問題方法寄生組合式繼承所謂寄生組合式繼承,即通過借用構(gòu)造函數(shù)來繼承屬性,通過原型鏈的混成形式來繼承方法。 寄生組合式繼承 組合繼承是JavaScript最常用的繼承模式。 不過,它也有自己的不足。 組合繼承最大的問題就是無論在什么情況下,都會調(diào)用兩次超類型構(gòu)造函數(shù)...
摘要:無限增殖返回蘋果返回香蕉返回返回使用的新語法方法會創(chuàng)建一個新對象,使用現(xiàn)有的對象來提供新創(chuàng)建的對象的。是新增的,用來規(guī)范原型式繼承。這里將返回的新對象放到子類的原型對象里面,這樣子類就擁有了父類的原型對象,也就實現(xiàn)了方法的繼承。 這是最后的最后了,我會順便總結(jié)一下各種繼承方式的學習和理解。(老板要求什么的,管他呢) 一、繼承-組合繼承、偽經(jīng)典繼承 showImg(https://seg...
閱讀 2096·2023-04-26 02:41
閱讀 2152·2021-09-24 09:47
閱讀 1553·2019-08-30 15:53
閱讀 1211·2019-08-30 13:01
閱讀 1892·2019-08-29 11:27
閱讀 2867·2019-08-28 17:55
閱讀 1763·2019-08-26 14:00
閱讀 3392·2019-08-26 10:18