色综合图-色综合图片-色综合图片二区150p-色综合图区-玖玖国产精品视频-玖玖香蕉视频

您的位置:首頁技術(shù)文章
文章詳情頁

淺談 JS 創(chuàng)建對象的 8 種模式

瀏覽:118日期:2024-05-24 11:32:41

1.Object 模式

var o1 = {};//字面量的表現(xiàn)形式var o2 = new Object;var o3 = new Object();var o4 = new Object(null);var o5 = new Object(undefined);var o6 = Object.create(Object.prototype);//等價于 var o = {};//即以 Object.prototype 對象為一個原型模板,新建一個以這個原型模板為原型的對象//區(qū)別var o7 = Object.create(null);//創(chuàng)建一個原型為 null 的對象

在 chrome 里查看各個新建對象的區(qū)別:淺談 JS 創(chuàng)建對象的 8 種模式

可以看出前6種模式創(chuàng)建出來的對象都是一樣的,第七種不同點在于其雖然也為 Object 對象但其無任何屬性(包括沒有任何可以繼承的屬性,因為創(chuàng)建的時候沒有指定其原型)

2.工廠模式

//工廠方法1 通過一個方法來創(chuàng)建對象 利用 arguments 對象獲取參數(shù)設(shè)置屬性(參數(shù)不直觀,容易出現(xiàn)問題)function createCar(){ var oTemp = new Object(); oTemp.name = arguments[0];//直接給對象添加屬性,每個對象都有直接的屬性 oTemp.age = arguments[1]; oTemp.showName = function () {alert(this.name); };//每個對象都有一個 showName 方法版本 return oTemp;}createCar('tom').showName();//在 JS 中沒有傳遞的實參,實際形參值為 undefined(這里的 age 為 undefined)createCar('tim',80).showName();alert(createCar('tom') instanceof Object);//true 判斷對象是否 Object 類或子類

//工廠方法2 通過傳參設(shè)置屬性(參數(shù)直觀明了)function createCar(name,age){ var oTemp = new Object(); oTemp.name = name;//直接給對象添加屬性,每個對象都有直接的屬性 oTemp.age = age; oTemp.showName = function () {alert(this.name); };//每個對象都有一個 showName 方法版本 return oTemp;}createCar('tom').showName();createCar('tim',80).showName();alert(createCar('tom') instanceof Object);//true 判斷對象是否 Object 類或子類

3.構(gòu)造器模式

//構(gòu)造器方法1function Car(sColor,iDoors){ //聲明為構(gòu)造器時需要將函數(shù)名首字母大寫 this.color = sColor; //構(gòu)造器內(nèi)直接聲明屬性 this.doors = iDoors; this.showColor = function(){return this.color; };//每個 Car 對象都有自己的 showColor方法版本 this.showDoor = function () {return this.doors; }}

使用方法1的問題很明顯,沒辦法是 showDoor 方法重用,每次新建一個對象就要在堆里新開辟一篇空間.改進(jìn)如下

//構(gòu)造器方法2function showDoor(){ //定義一個全局的 Function 對象 return this.doors;}function Car(sColor,iDoors){//構(gòu)造器 this.color = sColor; //構(gòu)造器內(nèi)直接聲明屬性 this.doors = iDoors; this.showColor = function(){return this.color; }; this.showDoor = showDoor();//每個 Car 對象共享同一個 showDoor 方法版本(方法有自己的作用域,不用擔(dān)心變量被共享)}alert(new Car('red',2).showColor());//通過構(gòu)造器創(chuàng)建一個對象并調(diào)用其對象方法

上面出現(xiàn)的問題就是語義不夠清除,體現(xiàn)不出類的封裝性,改進(jìn)為 prototype 模式

4.通過Function對象實現(xiàn)創(chuàng)建對象

我們知道每聲明一個函數(shù)實際是創(chuàng)建了一個Function 實例 JS 函數(shù).

function function_name(param1,param2){alert(param1);}//等價于var function_name = new Function('param1','pram2','alert(param1);');

var Car2 = new Function('sColor','iDoors', 'this.color = sColor;'+ 'this.doors = iDoors;'+ 'this.showColor = function(){ return this.color; }');alert(new Car2('blue',3).showColor());

5.prototype模式

類通過 prototype 屬性添加的屬性與方法都是綁定在這個類的 prototype 域(實際為一個 Prototype 對象)中,綁定到這個域中的屬性與方法只有一個版本,只會創(chuàng)建一次.類的實例對象可以直接像調(diào)用自己的屬性一樣調(diào)用該類的 prototype 域中的屬性與方法,類可以通過調(diào)用 prototype 屬性來間接調(diào)用prototype 域內(nèi)的屬性與方法.注意:通過類實例化出對象后對象內(nèi)無 prototype 屬性,但對象可直接像訪問屬性一樣的訪問類的 prototype 域的內(nèi)容,實例對象有個私有屬性proto,proto屬性內(nèi)含有類的 prototype 域內(nèi)的屬性與方法

方法1function Car3(){}//用空構(gòu)造函數(shù)設(shè)置類名Car3.prototype.color = 'blue';//每個對象都共享相同屬性Car3.prototype.doors = 3;Car3.prototype.drivers = new Array('Mike','John');Car3.prototype.showColor = function(){ alert(this.color);};//每個對象共享一個方法版本,省內(nèi)存。var car3_1 = new Car3();var car3_2 = new Car3();alert(car3_1.color);//bluealert(car3_2.color);//bluealert(Car3.prototype.color);//bluecar3_1.drivers.push('Bill');alert(car3_1.drivers);//'Mike','John','Bill'alert(car3_2.drivers);//'Mike','John','Bill'alert(Car3.prototype.drivers);//'Mike','John','Bill'//直接修改實例對象的屬性,解析器會先去找實例對象是否有這個屬性(不會去找實例對象的 _proto_ 屬性內(nèi)的那些類的 prototype 屬性,而是直接查看這個實例是否有對應(yīng)的屬性(與_proto_同級))//如果沒有則直接給這個實例對象添加該屬性,但不會修改類的prototype域的同名屬性,既實例對象的_proto_屬性內(nèi)的那些類 prototype 域?qū)傩圆粫恍薷腸ar3_1.color = 'red';//car3_1對象內(nèi)無名為 color 的對象屬性,故將該屬性添加到該對象上//解析器對實例對象讀取屬性值的時候會先查找該實例有無同名的直接屬性//如果沒有,則查找__proto__屬性內(nèi)保存的那些 當(dāng)前類的 prototype 域的屬性//有就返回,無則繼續(xù)查找是否有原型鏈中的對應(yīng)的方法屬性//有就返回,無則返回undefinedalert(car3_1.color);//redalert(car3_2.color);//bluealert(car3_2.color2);//undefined//直接修改類的 prototype 域內(nèi)的屬性,不會影響該類的實例對象的對象屬性,但會影響實例對象的_proto_屬性(_proto_屬性內(nèi)存放的是類的 prototype 域的內(nèi)容)Car3.prototype.color = 'black';alert(car3_1.color);//red 該對象有同名的直接屬性,故不會去_proto_屬性內(nèi)查找類的 prototype 域的屬性alert(car3_2.color);//black 受影響//直接修改實例對象的方法,解析器會先去找實例對象是否有這個方法(不會去找實例對象的 _proto_ 屬性內(nèi)的那些類的 prototype 域的方法,而是直接查看這個實例是否有對應(yīng)的方法(與_proto_同級))//如果沒有則直接給這個實例對象添加該方法,但不會修改類的prototype域的同名方法,既實例對象的_proto_屬性內(nèi)的那些類 prototype 域方法不會被修改//car3_1對象內(nèi)無名為 showColor 的對象方法屬性,故將該方法屬性添加到該對象上car3_1.showColor = function () { alert('new function');}//解析器對實例對象調(diào)用方法屬性的時候會先查找該實例有無同名的直接方法屬性//如果沒有,則查找_proto_屬性內(nèi)保存的那些 當(dāng)前類的 prototype 域的方法屬性//有就返回,無則繼續(xù)查找是否有原型鏈中的對應(yīng)的方法屬性//找到就返回,無則報錯car3_1.showColor();//new functioncar3_2.showColor();//bluecar3_1.abcd();//直接報錯//直接修改類的 prototype 域內(nèi)的方法屬性,不會影響該類的實例對象的方法屬性,但會影響實例對象的_proto_屬性(_proto_屬性內(nèi)存放的是類的 prototype 域的內(nèi)容)Car3.prototype.showColor = function () { alert('second function');}car3_1.showColor();//new function 該對象有同名的方法屬性,故不會去_proto_屬性內(nèi)查找類的 prototype 域的方法屬性car3_2.showColor();//second function 受影響

可以看出使用該方法雖然說打打減少了內(nèi)存的浪費,但依舊有問題,某個對象的屬性一旦改變,所有由該類實例化得到的對象的proto內(nèi)屬性值也會跟著變(實為引用),改進(jìn)如下

6.構(gòu)造器方式與原型方式的混合模式

//每個對象有專屬的屬性不會與其他對象共享function Car4(sColor,iDoors){ this._color = sColor;//私有屬性變量名稱頭加下劃線標(biāo)識 this._doors = iDoors; this.drivers = new Array('Mike','John');//公有屬性標(biāo)識}//所有對象共享一個方法版本,減少內(nèi)存浪費Car4.prototype.showColor = function () { alert(this._color);};var car4_1 = new Car4('red',4);var car4_2 = new Car4('blue',3);car4_1.drivers.push('Bill');alert(car4_1.drivers);//'Mike','John','Bill'alert(car4_2.drivers);//'Mike','John'

這也是常用的創(chuàng)建對象方式之一

7.動態(tài)原型模式

function Car5(sColor,iDoors,iMpg){ this.color = sColor; this.doors = iDoors; this.mpg = iMpg; this.drivers = new Array('Mike','John'); //使用標(biāo)志(_initialized)來判斷是否已給原型賦予了任何方法,保證方法永遠(yuǎn)只被創(chuàng)建并賦值一次 if(typeof Car5._initialized == 'undefined'){//因為這里的標(biāo)記是附加在類上,故如果后期直接對其進(jìn)行修改,還是有可能出現(xiàn)再次創(chuàng)建的情況Car5.prototype.showColor = function () {//為Car5添加一個存放在 prototype 域的方法 alert(this.color);};Car5._initialized = true;//設(shè)置一個靜態(tài)屬性 }}var car5_1 = new Car5('red',3,25);var car5_2 = new Car5('red',3,25);

這種模式使得定義類像強類型語言例如 java 等語言的定義模式

8.混合工廠模式

function Car6(){ var oTempCar = new Object; oTempCar.color = 'blue'; oTempCar.doors = 4; oTempCar.showColor = function () {alert(this.color); }; return oTempCar;}var car6 = new Car6();

由于在 Car6()構(gòu)造函數(shù)內(nèi)部調(diào)用了 new 運算符,所以將忽略第二個 new 運算符(位于構(gòu)造函數(shù)之外),在構(gòu)造函數(shù)內(nèi)部創(chuàng)建的對象被傳遞回變量car6,這種方式在對象方法的內(nèi)部管理方面與經(jīng)典方式(工廠方法)有著相同的問題.應(yīng)盡量避免

作者:Tomson原文地址:http://segmentfault.com/a/1190000003862596

標(biāo)簽: JavaScript
相關(guān)文章:
主站蜘蛛池模板: 成人18免费入口 | 三级中文字幕永久在线视频 | 色老久久精品偷偷鲁一区 | 久草手机在线观看视频 | 加勒比综合 | 理论片我不卡在线观看 | 欧美视频在线观看一区二区 | 国产乱子视频 | 日本高清不卡中文字幕 | 宅男噜噜噜一区二区三区 | 亚洲精品在线视频 | 成人精品一区二区www | 亚洲欧美日韩色 | 欧美日中文字幕 | 亚洲精品99久久久久久 | 国产成人精品久久 | 亚洲成人一区在线 | 精品国产区一区二区三区在线观看 | 亚洲国产毛片aaaaa无费看 | 中国女人毛片 | 91免费永久国产在线观看 | 国产三级小视频在线观看 | 日本欧美久久久久免费播放网 | 韩国一级毛片 | 在线精品免费视频 | 欧美成人精品手机在线观看 | 99精品在线| 老司机午夜精品网站在线观看 | 美国一级片免费 | 日本高清视频一区二区 | 国产成人亚洲欧美三区综合 | 亚洲成人福利 | 国产亚洲精品久久久久久久久激情 | 国内精品一区二区 | 在线播放精品一区二区啪视频 | 欧美一级α片毛片免费观看 | 全免费a级毛片免费看视频免 | 国产成人毛片精品不卡在线 | 国产精品手机在线亚洲 | 午夜影院a | 国产精品午夜波多野结衣性色 |