亚洲精品久久久中文字幕-亚洲精品久久片久久-亚洲精品久久青草-亚洲精品久久婷婷爱久久婷婷-亚洲精品久久午夜香蕉

您的位置:首頁技術文章
文章詳情頁

淺談 JS 創建對象的 8 種模式

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

1.Object 模式

var o1 = {};//字面量的表現形式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 對象為一個原型模板,新建一個以這個原型模板為原型的對象//區別var o7 = Object.create(null);//創建一個原型為 null 的對象

在 chrome 里查看各個新建對象的區別:淺談 JS 創建對象的 8 種模式

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

2.工廠模式

//工廠方法1 通過一個方法來創建對象 利用 arguments 對象獲取參數設置屬性(參數不直觀,容易出現問題)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 通過傳參設置屬性(參數直觀明了)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.構造器模式

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

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

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

上面出現的問題就是語義不夠清除,體現不出類的封裝性,改進為 prototype 模式

4.通過Function對象實現創建對象

我們知道每聲明一個函數實際是創建了一個Function 實例 JS 函數.

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 對象)中,綁定到這個域中的屬性與方法只有一個版本,只會創建一次.類的實例對象可以直接像調用自己的屬性一樣調用該類的 prototype 域中的屬性與方法,類可以通過調用 prototype 屬性來間接調用prototype 域內的屬性與方法.注意:通過類實例化出對象后對象內無 prototype 屬性,但對象可直接像訪問屬性一樣的訪問類的 prototype 域的內容,實例對象有個私有屬性proto,proto屬性內含有類的 prototype 域內的屬性與方法

方法1function Car3(){}//用空構造函數設置類名Car3.prototype.color = 'blue';//每個對象都共享相同屬性Car3.prototype.doors = 3;Car3.prototype.drivers = new Array('Mike','John');Car3.prototype.showColor = function(){ alert(this.color);};//每個對象共享一個方法版本,省內存。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_ 屬性內的那些類的 prototype 屬性,而是直接查看這個實例是否有對應的屬性(與_proto_同級))//如果沒有則直接給這個實例對象添加該屬性,但不會修改類的prototype域的同名屬性,既實例對象的_proto_屬性內的那些類 prototype 域屬性不會被修改car3_1.color = 'red';//car3_1對象內無名為 color 的對象屬性,故將該屬性添加到該對象上//解析器對實例對象讀取屬性值的時候會先查找該實例有無同名的直接屬性//如果沒有,則查找__proto__屬性內保存的那些 當前類的 prototype 域的屬性//有就返回,無則繼續查找是否有原型鏈中的對應的方法屬性//有就返回,無則返回undefinedalert(car3_1.color);//redalert(car3_2.color);//bluealert(car3_2.color2);//undefined//直接修改類的 prototype 域內的屬性,不會影響該類的實例對象的對象屬性,但會影響實例對象的_proto_屬性(_proto_屬性內存放的是類的 prototype 域的內容)Car3.prototype.color = 'black';alert(car3_1.color);//red 該對象有同名的直接屬性,故不會去_proto_屬性內查找類的 prototype 域的屬性alert(car3_2.color);//black 受影響//直接修改實例對象的方法,解析器會先去找實例對象是否有這個方法(不會去找實例對象的 _proto_ 屬性內的那些類的 prototype 域的方法,而是直接查看這個實例是否有對應的方法(與_proto_同級))//如果沒有則直接給這個實例對象添加該方法,但不會修改類的prototype域的同名方法,既實例對象的_proto_屬性內的那些類 prototype 域方法不會被修改//car3_1對象內無名為 showColor 的對象方法屬性,故將該方法屬性添加到該對象上car3_1.showColor = function () { alert('new function');}//解析器對實例對象調用方法屬性的時候會先查找該實例有無同名的直接方法屬性//如果沒有,則查找_proto_屬性內保存的那些 當前類的 prototype 域的方法屬性//有就返回,無則繼續查找是否有原型鏈中的對應的方法屬性//找到就返回,無則報錯car3_1.showColor();//new functioncar3_2.showColor();//bluecar3_1.abcd();//直接報錯//直接修改類的 prototype 域內的方法屬性,不會影響該類的實例對象的方法屬性,但會影響實例對象的_proto_屬性(_proto_屬性內存放的是類的 prototype 域的內容)Car3.prototype.showColor = function () { alert('second function');}car3_1.showColor();//new function 該對象有同名的方法屬性,故不會去_proto_屬性內查找類的 prototype 域的方法屬性car3_2.showColor();//second function 受影響

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

6.構造器方式與原型方式的混合模式

//每個對象有專屬的屬性不會與其他對象共享function Car4(sColor,iDoors){ this._color = sColor;//私有屬性變量名稱頭加下劃線標識 this._doors = iDoors; this.drivers = new Array('Mike','John');//公有屬性標識}//所有對象共享一個方法版本,減少內存浪費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'

這也是常用的創建對象方式之一

7.動態原型模式

function Car5(sColor,iDoors,iMpg){ this.color = sColor; this.doors = iDoors; this.mpg = iMpg; this.drivers = new Array('Mike','John'); //使用標志(_initialized)來判斷是否已給原型賦予了任何方法,保證方法永遠只被創建并賦值一次 if(typeof Car5._initialized == 'undefined'){//因為這里的標記是附加在類上,故如果后期直接對其進行修改,還是有可能出現再次創建的情況Car5.prototype.showColor = function () {//為Car5添加一個存放在 prototype 域的方法 alert(this.color);};Car5._initialized = true;//設置一個靜態屬性 }}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()構造函數內部調用了 new 運算符,所以將忽略第二個 new 運算符(位于構造函數之外),在構造函數內部創建的對象被傳遞回變量car6,這種方式在對象方法的內部管理方面與經典方式(工廠方法)有著相同的問題.應盡量避免

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

標簽: JavaScript
相關文章:
主站蜘蛛池模板: 超黄视频网站 | zzijzzij亚洲日本护士 | 国产精品成人在线播放 | 久久色婷婷 | 日韩欧美综合在线二区三区 | 国产一区曰韩二区欧美三区 | 久久午夜鲁丝片午夜精品 | 男女无遮挡边做边吃视频免费 | 一区二区视频 | 免费中文字幕乱码电影麻豆网 | 欧美日韩亚洲精品一区二区 | 无码中文字幕乱在线观看 | 一级中国乱子伦视频 | 香蕉久久夜色精品国产2020 | 尤物国产在线精品福利一区 | 在线观看激情偷拍视频 | 特级女人十八毛片a级 | 国产极品精频在线观看 | 成人特级毛片 | 蜜柚mv在线观看 | 免费国产综合视频在线看 | 黄色观看视频 | 亚洲一区二区三区四区热压胶 | 老外黑人一级毛片 | 国产精品国产精品国产专区不卡 | 婷婷国产偷v国产偷v亚洲 | a级一级毛片 | 日韩毛片久久91 | 一本色道久久综合狠狠躁篇 | 色欧美在线视频 | 三级中文字幕永久在线视频 | 黄色片网站免费 | 日本一级特黄完整大片 | 国内精品一区二区 | 成年黄色网址 | 欧美毛片免费看 | 国产人碰人摸人爱免费视频 | 野战好大好紧好爽视频 | 日本一级黄色毛片 | 好好的曰www视频在线观看 | 妖精视频永久在线入口 |