定义类或对象
學(xué)習(xí)總結(jié):
工廠方式
原始的方式(對象創(chuàng)建后動態(tài)定義對象的屬性)
創(chuàng)建對象 car,屬性:它的顏色是藍色,有四個門,每加侖油可以跑 25 英里。最后一個屬性實際上是指向函數(shù)的指針,意味著該屬性是個方法。
有一個問題,就是可能需要創(chuàng)建多個 car 的實例。
解決方案:工廠方式(函數(shù)封裝)
這使兩個對象具有相同的屬性,卻有不同的屬性值。
每次調(diào)用函數(shù) createCar(),都要創(chuàng)建新函數(shù) showColor(),意味著每個對象都有自己的 showColor() 版本。而事實上,每個對象都共享同一個函數(shù)。
在工廠函數(shù)外定義對象的方法 可避免以上問題
從功能上講,這樣解決了重復(fù)創(chuàng)建函數(shù)對象的問題;但是從語義上講,該函數(shù)不太像是對象的方法。
構(gòu)造函數(shù)方式
第一步選擇類名,即構(gòu)造函數(shù)的名字。根據(jù)慣例,這個名字的首字母大寫,以使它與首字母通常是小寫的變量名分開。除了這點不同,構(gòu)造函數(shù)看起來很像工廠函數(shù)。
與工廠方式的差別:
首先在構(gòu)造函數(shù)內(nèi)沒有創(chuàng)建對象,而是使用 this 關(guān)鍵字。
使用 new 運算符構(gòu)造函數(shù)時,在執(zhí)行第一行代碼前先創(chuàng)建一個對象,只有用 this 才能訪問該對象。
然后可以直接賦予 this 屬性,默認情況下是構(gòu)造函數(shù)的返回值(不必明確使用 return 運算符)。
現(xiàn)在,用 new 運算符和類名 Car 創(chuàng)建對象,就更像 ECMAScript 中一般對象的創(chuàng)建方式了。
就像工廠函數(shù),構(gòu)造函數(shù)會重復(fù)生成函數(shù),為每個對象都創(chuàng)建獨立的函數(shù)版本。
不過,與工廠函數(shù)相似,也可以用外部函數(shù)重寫構(gòu)造函數(shù),同樣地,這么做語義上無任何意義。這正是下面要講的原型方式的優(yōu)勢所在。
原型方式
該方式利用了對象的 prototype 屬性,可以把它看成創(chuàng)建新對象所依賴的原型。
這里,首先用空構(gòu)造函數(shù)來設(shè)置類名。然后所有的屬性和方法都被直接賦予 prototype 屬性。
在這段代碼中,首先定義構(gòu)造函數(shù)(Car),其中無任何代碼。
接下來的幾行代碼,通過給 Car 的 prototype 屬性添加屬性去定義 Car 對象的屬性。
調(diào)用 new Car() 時,原型的所有屬性都被立即賦予要創(chuàng)建的對象,意味著所有 Car 實例存放的都是指向 showColor() 函數(shù)的指針。
從語義上講,所有屬性看起來都屬于一個對象,因此解決了前面兩種方式存在的問題。
此外,使用這種方式,還能用 instanceof 運算符檢查給定變量指向的對象的類型。
原型方式的問題
這個構(gòu)造函數(shù)沒有參數(shù)。
使用原型方式,不能通過給構(gòu)造函數(shù)傳遞參數(shù)來初始化屬性的值,因為 Car1 和 Car2 的 color 屬性都等于 "blue",doors 屬性都等于 4,mpg 屬性都等于 25。
這意味著必須在對象創(chuàng)建后才能改變屬性的默認值,真正的問題出現(xiàn)在屬性指向的是對象,而不是函數(shù)時。
函數(shù)共享不會造成問題,但對象卻很少被多個實例共享。
屬性 drivers 是指向 Array 對象的指針,該數(shù)組中包含兩個名字 "Mike" 和 "John"。
由于 drivers 是引用值,Car 的兩個實例都指向同一個數(shù)組。
這意味著給 oCar1.drivers 添加值 "Bill",在 oCar2.drivers 中也能看到。
輸出這兩個指針中的任何一個,結(jié)果都是顯示字符串 "Mike,John,Bill"。
由于創(chuàng)建對象時有這么多問題,需要聯(lián)合使用構(gòu)造函數(shù)和原型方式。
混合的構(gòu)造函數(shù)/原型方式
聯(lián)合使用構(gòu)造函數(shù)和原型方式,就可像用其他程序設(shè)計語言一樣創(chuàng)建對象。
這種概念非常簡單,即用構(gòu)造函數(shù)定義對象的所有非函數(shù)屬性,用原型方式定義對象的函數(shù)屬性(方法)。
結(jié)果是,所有函數(shù)都只創(chuàng)建一次,而每個對象都具有自己的對象屬性實例。
現(xiàn)在就更像創(chuàng)建一般對象了。
所有的非函數(shù)屬性都在構(gòu)造函數(shù)中創(chuàng)建,意味著又能夠用構(gòu)造函數(shù)的參數(shù)賦予屬性默認值了。
因為只創(chuàng)建 showColor() 函數(shù)的一個實例,所以沒有內(nèi)存浪費。
此外,給 oCar1 的 drivers 數(shù)組添加 "Bill" 值,不會影響到 oCar2 的數(shù)組,所以輸出這些數(shù)組的值時,oCar1.drivers 顯示的是 "Mike,John,Bill",而 oCar2.drivers 顯示的是 "Mike,John"。
因為使用了原型方式,所以仍然能利用 instanceof 運算符來判斷對象的類型。
動態(tài)原型方法
動態(tài)原型方法的基本想法與混合的構(gòu)造函數(shù)/原型方式相同,即在構(gòu)造函數(shù)內(nèi)定義非函數(shù)屬性,而函數(shù)屬性則利用原型屬性定義。
唯一的區(qū)別是賦予對象方法的位置。
直到檢查 typeof Car._initialized 是否等于 "undefined" 之前,這個構(gòu)造函數(shù)都未發(fā)生變化。
這行代碼是動態(tài)原型方法中最重要的部分。
如果這個值未定義,構(gòu)造函數(shù)將用原型方式繼續(xù)定義對象的方法,然后把 Car._initialized 設(shè)置為 true。
如果這個值定義了(它的值為 true 時,typeof 的值為 Boolean),那么就不再創(chuàng)建該方法。
簡而言之,該方法使用標(biāo)志(_initialized)來判斷是否已給原型賦予了任何方法。
該方法只創(chuàng)建并賦值一次,傳統(tǒng)的 OOP 開發(fā)者會高興地發(fā)現(xiàn),這段代碼看起來更像其他語言中的類定義了。
混合工廠方式
這種方式通常是在不能應(yīng)用前一種方式時的變通方法。
它的目的是創(chuàng)建假構(gòu)造函數(shù),只返回另一種對象的新實例。
這段代碼看起來與工廠函數(shù)非常相似:
與經(jīng)典方式不同,這種方式使用 new 運算符,使它看起來像真正的構(gòu)造函數(shù):
由于在 Car() 構(gòu)造函數(shù)內(nèi)部調(diào)用了 new 運算符,所以將忽略第二個 new 運算符(位于構(gòu)造函數(shù)之外),在構(gòu)造函數(shù)內(nèi)部創(chuàng)建的對象被傳遞回變量 car。
這種方式在對象方法的內(nèi)部管理方面與經(jīng)典方式有著相同的問題。
強烈建議:除非萬不得已,還是避免使用這種方式。
-------------------------------------
如前所述,目前使用最廣泛的是混合的構(gòu)造函數(shù)/原型方式。
此外,動態(tài)原始方法也很流行,在功能上與構(gòu)造函數(shù)/原型方式等價。
可以采用這兩種方式中的任何一種。
不過不要單獨使用經(jīng)典的構(gòu)造函數(shù)或原型方式,因為這樣會給代碼引入問題。
轉(zhuǎn)載于:https://www.cnblogs.com/hiuman/p/7347414.html
總結(jié)
- 上一篇: 未能加载文件或程序集“Poderosa.
- 下一篇: noip2012-day2-t2