摘要:并且,在創(chuàng)建子類型的實(shí)例時(shí),無(wú)法向超類型的構(gòu)造函數(shù)傳遞參數(shù)。借用構(gòu)造函數(shù)經(jīng)典繼承在子類型構(gòu)造函數(shù)的內(nèi)部調(diào)用超類型構(gòu)造函數(shù)。缺點(diǎn)是同樣具有構(gòu)造函數(shù)模式創(chuàng)建對(duì)象的固有弊端構(gòu)造函數(shù)中煩人方法函數(shù)對(duì)象重復(fù)創(chuàng)建。
創(chuàng)建對(duì)象的幾種方式
在邏輯上從低級(jí)到高級(jí):工廠模式、構(gòu)造函數(shù)模式、原型模式、組合模式。當(dāng)然還有其他模式,但是這四者邏輯關(guān)系強(qiáng),總結(jié)起來(lái)很有感覺(jué)。之所以和繼承一起分析,也是因?yàn)檫壿嬯P(guān)系很清晰:原型模式對(duì)應(yīng)原型鏈繼承,構(gòu)造函數(shù)模式對(duì)應(yīng)借用構(gòu)造函數(shù)模式繼承,組合模式對(duì)應(yīng)組合繼承。邏輯上按照“哪個(gè)模式有什么缺點(diǎn),為什么有這個(gè)缺點(diǎn),我們?cè)趺唇鉀Q這個(gè)缺點(diǎn)”逐步分析,這樣分析完后就會(huì)豁然開(kāi)朗。
1)工廠模式使用函數(shù)創(chuàng)建對(duì)象,該函數(shù)來(lái)封裝創(chuàng)建對(duì)象的細(xì)節(jié)。
function createObject(para1,para2,para3){ var o = new Object();//顯式創(chuàng)建對(duì)象 o.colors = [para1, para2, para3]; o.sayColors = function() { console.log(this.colors[0]); } return o;//返回對(duì)象 } var ob1 = createObject("red", "green", "blue"); console.log(ob1); console.log(ob1.colors); ob1.sayColors(); console.log(ob1 instanceof createObject);//false,無(wú)法判斷對(duì)象的類型 缺點(diǎn):無(wú)法判斷對(duì)象類型。2)構(gòu)造函數(shù)模式
通過(guò)構(gòu)造函數(shù)創(chuàng)建的實(shí)例被標(biāo)識(shí)為一種特定的類型,可以通過(guò)instanceof 判斷對(duì)象類型。
function createObject(para1, para2, para3) { //通過(guò)this完成函數(shù)屬性定義,不用顯示創(chuàng)建對(duì)象,因此也不用返回對(duì)象 this.colors = [ para1, para2, para3 ]; this.sayColors = function () { console.log(this.colors[0]); } } var ob1 = new createObject("red", "green", "blue"); console.log(ob1); console.log(ob1.colors); ob1.sayColors(); console.log(ob1 instanceof createObject); //true,可以判斷對(duì)象的類型
缺點(diǎn):通過(guò)構(gòu)造函數(shù)創(chuàng)建的實(shí)例具有不同的方法和屬性,屬性可以不同,這對(duì)實(shí)例來(lái)說(shuō)是好的,我們希望實(shí)例屬性獨(dú)立。但是方法即函數(shù),函數(shù)即對(duì)象,也就是說(shuō)創(chuàng)建了太多重復(fù)的對(duì)象。
var ob1 = new createObject("red", "green", "blue"); var ob2 = new createObject("red", "green", "blue"); alert(ob1.sayColors == ob2.sayColors);//false,不同實(shí)例具有不同的方法
解決方式:把方法的定義放到構(gòu)造函數(shù)外部,即在構(gòu)造函數(shù)內(nèi)部引用外部全局函數(shù)。這樣就可以一次定義,多次引用。但是當(dāng)外部全局函數(shù)增多時(shí),明顯降低了封裝性,《JavaScript精粹》上提到,全局對(duì)象是EScript的一大敗筆。
值得一提的是,構(gòu)造函數(shù)創(chuàng)建的實(shí)例中的引用類型屬性是很特殊的,這一點(diǎn)會(huì)隨后提到。
3) 原型模式:每一個(gè)函數(shù)都有一個(gè)prototype屬性,這個(gè)屬性指向通過(guò)構(gòu)造函數(shù)創(chuàng)建的實(shí)例對(duì)象的原型對(duì)象。原型對(duì)象的方法和屬性可以被它的所有實(shí)例共享。因此,通過(guò)把屬性和方法添加到實(shí)例的原型對(duì)象上,可以實(shí)現(xiàn)屬性和方法共享。
缺點(diǎn):“成也蕭何,敗也蕭何”,原型模式的缺點(diǎn)就在于過(guò)強(qiáng)的共享能力,方法的共享可以減少多余的對(duì)象實(shí)例創(chuàng)建。但是屬性共享導(dǎo)致實(shí)例難以擁有自己獨(dú)特屬性。當(dāng)然,如果是一些不會(huì)修改的屬性值,共享也就罷了;但是如果是需要修改的屬性,并且該屬性值是引用類型(基本類型屬性值可以在實(shí)例中定義,會(huì)覆蓋掉原型屬性,但是不會(huì)修改原型屬性,其他的實(shí)例訪問(wèn)該屬性依舊對(duì)應(yīng)原型屬性),那么實(shí)例對(duì)這個(gè)屬性值的修改就會(huì)在原型中反映出來(lái),這其實(shí)就是修改了原型。糟糕的是其他實(shí)例中的該屬性也同步變化,然后就會(huì)出現(xiàn)奇怪的問(wèn)題。
4) 組合模式(最常用的一種對(duì)象創(chuàng)建方式,兼顧優(yōu)點(diǎn),避免缺點(diǎn))
:使用構(gòu)造函數(shù)模式定義各個(gè)實(shí)例屬性,使用原型模式定義方法和共享的屬性。
補(bǔ)充關(guān)于對(duì)象的幾個(gè)方法:
isPrototypeOf(): 確定一個(gè)對(duì)象是否是另一個(gè)對(duì)象的原型,只要是原型鏈中出現(xiàn)的原型,就返回true,使用方法:
alert(createObject.prototype.isPrototypeOf(ob1));//rue
instanceof操作符:檢測(cè)是否是某一構(gòu)造函數(shù)的實(shí)例,前面的參數(shù)是實(shí)例, 后面的的參數(shù)是構(gòu)造函數(shù)名,只要是原型鏈中出現(xiàn)的構(gòu)造函數(shù)就返回true。
alert(ob1 instanceof createObject);//true
hasOwnProperty(): 檢測(cè)一個(gè)實(shí)例是否擁有某個(gè)屬性,使用方法
alert(ob1.hasOwnProperty("colors"));//true
in操作符:多帶帶使用時(shí)可以檢查實(shí)例屬性或者原型屬性是否存在,in后跟的一般是實(shí)例,因此可以理解為檢查實(shí)例以及實(shí)例對(duì)應(yīng)的原型中是否有這個(gè)屬性或非法。使用方法:
alert("sayColors" in ob1);//true alert("sayColors" in createObject);//false,直接對(duì)原型檢查沒(méi)意義
for in 的另一種用法,類似于數(shù)組的forEach()方法,是一個(gè)循環(huán),返回實(shí)例或原型中的可枚舉的屬性。
繼承的實(shí)現(xiàn): 1.原型鏈
:把超類型的實(shí)例復(fù)制給子類型的原型,這樣超類型的方法和屬性就由子類型繼承。
問(wèn)題:子類型原型會(huì)繼承超類型實(shí)例的屬性,如果這個(gè)屬性值是引用類型,就會(huì)導(dǎo)致子類型的所有實(shí)例都共享了這個(gè)屬性,導(dǎo)致不同實(shí)例屬性的耦合,這是原型模式創(chuàng)建對(duì)象的固有問(wèn)題。并且,在創(chuàng)建子類型的實(shí)例時(shí),無(wú)法向超類型的構(gòu)造函數(shù)傳遞參數(shù)。因此,實(shí)際中很少多帶帶使用原型鏈。
2 借用構(gòu)造函數(shù)(經(jīng)典繼承)在子類型構(gòu)造函數(shù)的內(nèi)部調(diào)用超類型構(gòu)造函數(shù)。這個(gè)方法之所以被稱為借用構(gòu)造函數(shù),我覺(jué)得就是因?yàn)檫@種方法和前面介紹的通過(guò)構(gòu)造函數(shù)創(chuàng)建實(shí)例的私有屬性是一樣的道理,只不過(guò)是在子類型構(gòu)造函數(shù)內(nèi)部調(diào)用了超類型構(gòu)造函數(shù)。
而且可以在創(chuàng)建子類型實(shí)例時(shí)向超類型傳遞參數(shù),因?yàn)檫@就相當(dāng)于調(diào)用了一個(gè)函數(shù),函數(shù)當(dāng)然是可以有參數(shù)的。
缺點(diǎn)是同樣具有構(gòu)造函數(shù)模式創(chuàng)建對(duì)象的固有弊端:構(gòu)造函數(shù)中煩人方法(函數(shù)對(duì)象)重復(fù)創(chuàng)建。并且,只有在超類型構(gòu)造函數(shù)中定義的屬性和方法才會(huì)被繼承,通過(guò)超類型原型定義的方法和屬性對(duì)子類型不可見(jiàn),這是因?yàn)橹粓?zhí)行了構(gòu)造函數(shù)內(nèi)部的語(yǔ)句。因此實(shí)際中這個(gè)方法也很少多帶帶使用。
3 組合繼承(偽經(jīng)典模式繼承)
將原型鏈繼承和借用構(gòu)造函數(shù)模式組合到一起,使用原型鏈實(shí)現(xiàn)對(duì)原型屬性和方法的繼承(實(shí)現(xiàn)了方法復(fù)用),但是通過(guò)借用構(gòu)造函數(shù)實(shí)現(xiàn)對(duì)實(shí)例屬性的繼承(實(shí)現(xiàn)了實(shí)例屬性私有)。避免了缺陷,融合了優(yōu)點(diǎn),是最常用的繼承模式,而且,instanceof操作符和isPrototypeOf()都適用于組合繼承創(chuàng)建的對(duì)象。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/80555.html
摘要:介一回,偶們來(lái)聊一下用中的類,有些盆友可能用過(guò)或者的,知道語(yǔ)法糖,可是在中并沒(méi)有,中需要用到構(gòu)造函數(shù)來(lái)模擬類。而且要注意一點(diǎn),構(gòu)造函數(shù)沒(méi)有語(yǔ)句,是自動(dòng)返回。 本回內(nèi)容介紹 上一回聊到JS的Function類型,做了柯里化,數(shù)組去重,排序的題。 介一回,偶們來(lái)聊一下用JS中的類,有些盆友可能用過(guò)ES6或者TypeScript的,知道Class語(yǔ)法糖,可是在ES5中并沒(méi)有,ES5中需要用到...
摘要:在最開(kāi)始的時(shí)候,原型對(duì)象的設(shè)計(jì)主要是為了獲取對(duì)象的構(gòu)造函數(shù)。同理數(shù)組通過(guò)調(diào)用函數(shù)通過(guò)調(diào)用原型鏈中描述了原型鏈的概念,并將原型鏈作為實(shí)現(xiàn)繼承的主要方法。 對(duì)象的創(chuàng)建 在JavaScript中創(chuàng)建一個(gè)對(duì)象有三種方式??梢酝ㄟ^(guò)對(duì)象直接量、關(guān)鍵字new和Object.create()函數(shù)來(lái)創(chuàng)建對(duì)象。 1. 對(duì)象直接量 創(chuàng)建對(duì)象最直接的方式就是在JavaScript代碼中使用對(duì)象直接量。在ES5...
摘要:高程讀書(shū)筆記第六章理解對(duì)象創(chuàng)建自定義對(duì)象的方式有創(chuàng)建一個(gè)實(shí)例,然后為它添加屬性和方法。創(chuàng)建了自定義的構(gòu)造函數(shù)之后,其原型對(duì)象默認(rèn)只會(huì)取得屬性至于其他方法都是從繼承而來(lái)的。 JS高程讀書(shū)筆記--第六章 理解對(duì)象 創(chuàng)建自定義對(duì)象的方式有創(chuàng)建一個(gè)Object實(shí)例,然后為它添加屬性和方法。還可用創(chuàng)建對(duì)象字面量的方式 屬性類型 ECMAScript在定義只有內(nèi)部采用的特性時(shí),描述了屬性的各種特征...
摘要:由構(gòu)造函數(shù)返回的對(duì)象就是表達(dá)式的結(jié)果。如果構(gòu)造函數(shù)沒(méi)有顯式返回一個(gè)對(duì)象,則使用步驟創(chuàng)建的對(duì)象。運(yùn)算符返回一個(gè)布爾值,表示對(duì)象是否為某個(gè)構(gòu)造函數(shù)的實(shí)例。 面向?qū)ο?本人能力有限,有誤請(qǐng)斧正 本文旨在復(fù)習(xí)面向?qū)ο?不包含es6) 本文學(xué)習(xí)思維 創(chuàng)建對(duì)象的方式,獲取對(duì)象屬性 構(gòu)造函數(shù),構(gòu)造函數(shù)的new 做了什么 原型與原型對(duì)象 原型鏈 繼承(借用構(gòu)造繼承、原型繼承、組合繼承、寄生組合繼承)...
showImg(http://img3.douban.com/lpic/s8958650.jpg); 0x00 javascript組成 ECMAScript(-265)核心語(yǔ)言部分 DOM文檔對(duì)象模型(DOM1、2、3) BOM瀏覽器對(duì)象模型(提供與瀏覽器交互的接口和方法) 0x01 async 異步加載 執(zhí)行順序不定 charset defer 延遲加載,立即下載腳本但不執(zhí)行 src ...
閱讀 1101·2021-11-15 18:00
閱讀 2815·2021-09-22 15:18
閱讀 1977·2021-09-04 16:45
閱讀 758·2019-08-30 15:55
閱讀 3870·2019-08-30 13:10
閱讀 1345·2019-08-30 11:06
閱讀 1994·2019-08-29 12:51
閱讀 2302·2019-08-26 13:55