摘要:三種使用構(gòu)造函數(shù)創(chuàng)建對象的方法和的作用都是在某個(gè)特殊對象的作用域中調(diào)用函數(shù)。這種方式還支持向構(gòu)造函數(shù)傳遞參數(shù)。叫法上把函數(shù)叫做構(gòu)造函數(shù),其他無區(qū)別適用情境可以在特殊的情況下用來為對象創(chuàng)建構(gòu)造函數(shù)。
一、工廠模式
工廠模式:使用字面量和object構(gòu)造函數(shù)會(huì)有很多重復(fù)代碼,在此基礎(chǔ)上改進(jìn)
解決了多個(gè)相似對象的問題,但沒有解決對象識(shí)別的問題(即怎樣知道一個(gè)對象的類型)
與工廠模式創(chuàng)建對象的不同之處:沒有顯示創(chuàng)建對象,直接將屬性和方法賦給this對象,沒有return語句。默認(rèn)return的是this對象。
構(gòu)造函數(shù)本身也是函數(shù),只是可以用來創(chuàng)建對象,所以借鑒自其他面向?qū)ο笳Z言,構(gòu)造函數(shù)始終應(yīng)該以一個(gè)大寫字母開頭,非構(gòu)造函數(shù)用一個(gè)小寫字母開頭,用于區(qū)別構(gòu)造函數(shù)與其他普通函數(shù)。
new操作符創(chuàng)建對象實(shí)例,經(jīng)歷4個(gè)步驟:
1、創(chuàng)建一個(gè)新對象
2、講構(gòu)造函數(shù)的作用域賦給新對象(所以此時(shí)this指向這個(gè)新對象)
3、執(zhí)行構(gòu)造函數(shù)中的代碼(為這個(gè)新對象添加屬性)
4、返回新對象
上面的實(shí)例a又一個(gè)constructor(構(gòu)造函數(shù))屬性指向Person。
相比較工廠模式的有點(diǎn):有constructor屬相,可以標(biāo)志為一種特性的類型。
但實(shí)際用來檢測對象類型,instanceod更方便些,所以instanceof比較的是constructor屬性。
三種使用構(gòu)造函數(shù)創(chuàng)建對象的方法:
call和apply的作用都是在某個(gè)特殊對象的作用域中調(diào)用Person()函數(shù)。那么上例中,otherPerson的作用域中調(diào)用Person函數(shù),this指向otherPerson對象,執(zhí)行構(gòu)造函數(shù)中的內(nèi)容,this.name指otherPerson.name=‘shirley’
構(gòu)造函數(shù)模式的缺點(diǎn):每創(chuàng)建一個(gè)實(shí)例都要執(zhí)行一遍構(gòu)造函數(shù)的語句,每個(gè)實(shí)例有不同的屬性值很正常,也有許多內(nèi)容一模一樣的方法,這些方法重復(fù)創(chuàng)建(實(shí)際是new function實(shí)例,所以person1.sayname!=otherPerson.sayname。因?yàn)閟ayName方法是不同實(shí)例,引用地址不同)則顯得冗余。
很明顯,如果實(shí)例引用同一個(gè)sayName實(shí)例(同一個(gè)方法)就能夠解決上述問題。
Person的sayName引用的都是同一個(gè)sayName函數(shù),即全局變量中的sayName函數(shù)。
利用每個(gè)函數(shù)都有的一個(gè)prototype(原型)屬性。這個(gè)屬性是一個(gè)指針,指向一個(gè)對象,這個(gè)對象的用途是包含可以由特定類型的所有實(shí)例共享的屬性和方法。(解決了構(gòu)造函數(shù)模式的缺點(diǎn))
prototype就是通過調(diào)用構(gòu)造函數(shù)而創(chuàng)建的那個(gè)對象實(shí)例的原型對象。(就是所創(chuàng)建的對象的原型,例如:var person1=new Person(’linda‘,15)person1的原型為Person。otherPerson=new Object() otherPerson的原型為Object)
例子:
判斷一個(gè)對象的prototype是否指向某對象
訪問一個(gè)對象的prototype屬性
Firef、Safari、Chrome中支持一個(gè)屬性__proto__可以訪問到prototype
注意: JavaScript 中任意對象都有一個(gè)內(nèi)置屬性 [[Prototype]] ,在ES5之前沒有標(biāo)準(zhǔn)的方法訪問這個(gè)內(nèi)置屬性,但是大多數(shù)瀏覽器都支持通過__proto__來訪問。以下統(tǒng)一使用__proto__來訪問 [[Prototype]],在實(shí)際開發(fā)中是不能這樣訪問的。(摘自:https://segmentfault.com/a/11...)
ES5中增加了一個(gè)新方法,Object.getPrototyOf()
“原型最初只包含constructor屬性”即,對象的constructor保存在原型屬性中。
對象實(shí)例不能改變原型中的值,所以當(dāng)我們試圖改變原型中的值時(shí),會(huì)在實(shí)例中新添加一個(gè)相同名稱的屬性。當(dāng)我們訪問這個(gè)屬性時(shí),就會(huì)優(yōu)先返回實(shí)例中的屬性,這就是覆蓋了原型的屬性。
那么我們怎么確定一個(gè)屬性是來自對象實(shí)例還是來自對象的原型,使用Object對象的hasOwnProperty()方法可以檢測屬性是否存在于對象實(shí)例中,若存在,則訪問的屬性必定是來自對象實(shí)例,因?yàn)楫?dāng)訪問一個(gè)屬性時(shí),先搜索對象屬性若不存在才會(huì)去搜索對象的原型屬性的。
delete可以刪除實(shí)例的屬性,但不能刪除對象原型中的屬性。
對象、構(gòu)造函數(shù)(constructor)和原型(Prototype)的聯(lián)系:
如下圖
person1和person2實(shí)例中的prototype屬性中保存的是Person的原型,原型里有constructor屬性又指向Person。所以對象和constructor之間是通過原型聯(lián)系起來的。
確定屬性是原型中的屬性:
in操作符只要通過對象能夠訪問到屬性就返回true,不管是實(shí)例的屬性還是原型中的屬性,所以通過in操作符返回true兒hasOwnProperty()返回false就可以確定屬性是原型中的屬性。
用字面量法定義Person的prototype屬性:
會(huì)造成constructor屬性不再指向Person
我們知道,沒創(chuàng)建一個(gè)函數(shù),就會(huì)同時(shí)創(chuàng)建它的prototype對象,這個(gè)對象也會(huì)自動(dòng)獲得constructor屬性。使用字面量定義prototype會(huì)重寫這個(gè)對象,因此constructor會(huì)變成新的對象的constructor屬性(指向object構(gòu)造函數(shù))。
打印person2顯示:
紅框內(nèi)沒有constructor屬性。我們知道person2.constructor會(huì)尋找person2對象中的constructor對象中的constructor對象,person2實(shí)例對象中沒有,尋找原型中(紅框)也沒有,繼續(xù)尋找prototype的原型對象即object對象,所以,person2.constructor===Object true;
原型模式創(chuàng)建對象是在函數(shù)構(gòu)造模式的基礎(chǔ)上解決共有方法和屬性的,那么函數(shù)構(gòu)造模式是為了解決字面量法的無法判斷是哪個(gè)對象的問題而出現(xiàn),怎么判斷?通過對象的constructor屬性判斷,現(xiàn)在原型的constructor都指向?qū)ο?,就把這個(gè)優(yōu)勢抹去了,所以出現(xiàn)下面這樣的方法來保存這個(gè)特性。
這樣做與原來的差別是:constructor屬性的[[Enumberable]]特性被設(shè)置為true,原來是false(不可枚舉)。所以如果使用兼容EXMAScript5的JavaScript引擎,可以使用Object.defineProperty()
原型具有動(dòng)態(tài)性。
構(gòu)造函數(shù)的原型改變會(huì)立即反映到所有實(shí)例中,但如果是重新寫一個(gè)原型對象則不會(huì)了
原因:person1的構(gòu)造函數(shù)會(huì)自動(dòng)指向一個(gè)原型對象,而保存的是這個(gè)原型對象的指針,新建一個(gè)prototype對象后,在堆內(nèi)存中開辟了一個(gè)新的對象空間,在person2中保存的是這個(gè)新對象的引用指針,所以兩者不同。
原型模式很少會(huì)多帶帶使用,因?yàn)樗袑傩远际枪蚕淼?,但?shí)力一般都是要有屬于自己的全部屬性的。原型模式無法做到,所以這是原型模式的缺點(diǎn)。
創(chuàng)建自定義類型的最常見方式,構(gòu)造函數(shù)模式用于定義實(shí)例屬性,原型模式用于定義方法和共享的屬性。
結(jié)果每個(gè)人實(shí)例都有自己的一份實(shí)例屬性的副本,同時(shí)又共享著對方法的引用,最大限度地節(jié)省了內(nèi)存。這種方式還支持向構(gòu)造函數(shù)傳遞參數(shù)。(既有構(gòu)造函數(shù)模式的優(yōu)點(diǎn)又有原型模式的優(yōu)點(diǎn))
在構(gòu)造函數(shù)中判斷是否存在sayName函數(shù),如果不存在添加到原型中,下圖創(chuàng)建了兩次對象,調(diào)用兩次構(gòu)造函數(shù),但if的判斷只執(zhí)行一次,在第一次執(zhí)行。
六、寄生構(gòu)造函數(shù)模式與工廠模式在寫法上紅框圈出不同之外一模一樣。叫法上把Person函數(shù)叫做構(gòu)造函數(shù),其他無區(qū)別
適用情境:
可以在特殊的情況下用來為對象創(chuàng)建構(gòu)造函數(shù)。假如我們想創(chuàng)建一個(gè)具有額外方法的特殊數(shù)組。
穩(wěn)妥對象:沒有公共屬性,而且其方法也不引用this的對象。
穩(wěn)妥對象最適合在一些安全的環(huán)境中(這些環(huán)境中會(huì)禁止是使用this和new),或者在防止數(shù)據(jù)被其他應(yīng)用程序(如Mashup程序)改動(dòng)時(shí)使用。
穩(wěn)妥構(gòu)造函數(shù)與寄生構(gòu)造函數(shù)類似的模式。不同點(diǎn):1、新創(chuàng)建對象的實(shí)例方法不引用this,2、不適用new操作符調(diào)用構(gòu)造函數(shù)。
所以,使用穩(wěn)妥構(gòu)造函數(shù)模式創(chuàng)建的對象與構(gòu)造函數(shù)之間沒有關(guān)系,無法用instanceod判斷所屬類型。
之所以穩(wěn)妥,是因?yàn)槌藄ayName方法外部無法對傳入構(gòu)造函數(shù)中的原始數(shù)據(jù)進(jìn)行訪問。即使可以給這個(gè)對象添加方法或數(shù)據(jù)成員。
使用環(huán)境:某些安全執(zhí)行環(huán)境下使用(ADsafe和Caja)
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/100735.html
摘要:繼承的是超類型中構(gòu)造函數(shù)中的屬性,如上繼承了屬性,但沒有繼承原型中的方法。上述造成的結(jié)果是子類型實(shí)例中有兩組超類型的構(gòu)造函數(shù)中定義的屬性,一組在子類型的實(shí)例中,一組在子類型實(shí)例的原型中。 ECMAScript只支持實(shí)現(xiàn)繼承,主要依靠原型鏈來實(shí)現(xiàn)。與實(shí)現(xiàn)繼承對應(yīng)的是接口繼承,由于script中函數(shù)沒有簽名,所以無法實(shí)現(xiàn)接口繼承。 一、原型鏈 基本思想:利用原型讓一個(gè)引用類型繼承另一個(gè)引用...
摘要:創(chuàng)建一個(gè)新對象將構(gòu)造函數(shù)的作用域賦給新對象因此就指向了這個(gè)新對象執(zhí)行構(gòu)造函數(shù)中的代碼為這個(gè)新對象添加屬性返回新對象。 本章內(nèi)容 理解對象屬性 理解并創(chuàng)建對象 理解繼承 ECMA-262把對象定義為:無序?qū)傩缘募?,其屬性可以包含基本值、對象或者函?shù) 理解對象 創(chuàng)建對象 創(chuàng)建自定義對象的最簡單方式就是創(chuàng)建一個(gè)Object的實(shí)例,再為它添加屬性和方法。 var person = new...
摘要:高程讀書筆記第六章理解對象創(chuàng)建自定義對象的方式有創(chuàng)建一個(gè)實(shí)例,然后為它添加屬性和方法。創(chuàng)建了自定義的構(gòu)造函數(shù)之后,其原型對象默認(rèn)只會(huì)取得屬性至于其他方法都是從繼承而來的。 JS高程讀書筆記--第六章 理解對象 創(chuàng)建自定義對象的方式有創(chuàng)建一個(gè)Object實(shí)例,然后為它添加屬性和方法。還可用創(chuàng)建對象字面量的方式 屬性類型 ECMAScript在定義只有內(nèi)部采用的特性時(shí),描述了屬性的各種特征...
摘要:第六章抽象本章會(huì)介紹如何將語句組織成函數(shù)。關(guān)鍵字參數(shù)和默認(rèn)值目前為止,我們使用的參數(shù)都是位置參數(shù),因?yàn)樗鼈兊奈恢煤苤匾?,事?shí)上比它們的名字更重要。參數(shù)前的星號(hào)將所有值放置在同一個(gè)元祖中。函數(shù)內(nèi)的變量被稱為局部變量。 第六章:抽象 本章會(huì)介紹如何將語句組織成函數(shù)。還會(huì)詳細(xì)介紹參數(shù)(parameter)和作用域(scope)的概念,以及遞歸的概念及其在程序中的用途。 懶惰即美德 斐波那契數(shù)...
摘要:寫在開頭本篇是小紅書筆記的第六篇,也許你會(huì)奇怪第六篇筆記才寫語法基礎(chǔ),筆者是不是穿越了??梢撇焦P者的文章中替換方式參考文檔高級(jí)程序設(shè)計(jì)作者以樂之名本文原創(chuàng),有不當(dāng)?shù)牡胤綒g迎指出。 showImg(https://segmentfault.com/img/bVblGMc?w=600&h=400); 寫在開頭 本篇是小紅書筆記的第六篇,也許你會(huì)奇怪第六篇筆記才寫語法基礎(chǔ),筆者是不是穿越了。...
閱讀 2657·2021-09-26 10:13
閱讀 6190·2021-09-08 10:46
閱讀 752·2019-08-30 15:53
閱讀 3026·2019-08-29 16:13
閱讀 2814·2019-08-26 12:23
閱讀 3540·2019-08-26 11:24
閱讀 1186·2019-08-23 18:09
閱讀 1083·2019-08-23 17:08