电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

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

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

瀏覽:145日期: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
相關文章:
主站蜘蛛池模板: sus630/303cu不锈钢棒,440C/430F/17-4ph不锈钢研磨棒-江苏德镍金属科技有限公司 | 创客匠人-让IP变现不走弯路 | 盛源真空泵|空压机-浙江盛源空压机制造有限公司-【盛源官网】 | 贵州成人高考网_贵州成考网| 宝鸡市人民医院 | 卫生纸复卷机|抽纸机|卫生纸加工设备|做卫生纸机器|小型卫生纸加工需要什么设备|卫生纸机器设备多少钱一台|许昌恒源纸品机械有限公司 | 英思科GTD-3000EX(美国英思科气体检测仪MX4MX6)百科-北京嘉华众信科技有限公司 | 顶呱呱交易平台-行业领先的公司资产交易服务平台 | 双舌接地线-PC68数字式高阻计-ZC36|苏海百科 | 超声波焊接机_超音波熔接机_超声波塑焊机十大品牌_塑料超声波焊接设备厂家 | 沧州友城管业有限公司-内外涂塑钢管-大口径螺旋钢管-涂塑螺旋管-保温钢管生产厂家 | 闪蒸干燥机-喷雾干燥机-带式干燥机-桨叶干燥机-[常州佳一干燥设备] | 电磁流量计_智能防腐防爆管道式计量表-金湖凯铭仪表有限公司 | 避光流动池-带盖荧光比色皿-生化流动比色皿-宜兴市晶科光学仪器 东莞爱加真空科技有限公司-进口真空镀膜机|真空镀膜设备|Polycold维修厂家 | 馋嘴餐饮网_餐饮加盟店火爆好项目_餐饮连锁品牌加盟指南创业平台 | 钢格板|镀锌钢格板|热镀锌钢格板|格栅板|钢格板|钢格栅板|热浸锌钢格板|平台钢格板|镀锌钢格栅板|热镀锌钢格栅板|平台钢格栅板|不锈钢钢格栅板 - 专业钢格板厂家 | 润滑脂-高温润滑脂-轴承润滑脂-食品级润滑油-索科润滑油脂厂家 | 云南标线|昆明划线|道路标线|交通标线-就选云南云路施工公司-云南云路科技有限公司 | 实验室隔膜泵-无油防腐蚀隔膜泵-耐腐蚀隔膜真空泵-杭州景程仪器 电杆荷载挠度测试仪-电杆荷载位移-管桩测试仪-北京绿野创能机电设备有限公司 | 破碎机锤头_耐磨锤头_合金锤头-鼎成机械一站式耐磨铸件定制服务 微型驱动系统解决方案-深圳市兆威机电股份有限公司 | 自动螺旋上料机厂家价格-斗式提升机定制-螺杆绞龙输送机-杰凯上料机 | 焊接烟尘净化器__焊烟除尘设备_打磨工作台_喷漆废气治理设备 -催化燃烧设备 _天津路博蓝天环保科技有限公司 | 卸料器-卸灰阀-卸料阀-瑞安市天蓝环保设备有限公司 | 智慧钢琴-电钢琴-便携钢琴-数码钢琴-深圳市特伦斯乐器有限公司 | 变位机,焊接变位机,焊接变位器,小型变位机,小型焊接变位机-济南上弘机电设备有限公司 | 仿清水混凝土_清水混凝土装修_施工_修饰_保护剂_修补_清水混凝土修复-德州忠岭建筑装饰工程 | 淄博不锈钢无缝管,淄博不锈钢管-鑫门物资有限公司 | 环氧乙烷灭菌器_压力蒸汽灭菌器_低温等离子过氧化氢灭菌器 _低温蒸汽甲醛灭菌器_清洗工作站_医用干燥柜_灭菌耗材-环氧乙烷灭菌器_脉动真空压力蒸汽灭菌器_低温等离子灭菌设备_河南省三强医疗器械有限责任公司 | 岩石钻裂机-液压凿岩机-劈裂机-挖改钻_湖南烈岩科技有限公司 | 无压烧结银_有压烧结银_导电银胶_导电油墨_导电胶-善仁(浙江)新材料 | 包头市鑫枫装饰有限公司| 塑钢课桌椅、学生课桌椅、课桌椅厂家-学仕教育设备首页 | 制氮设备-变压吸附制氮设备-制氧设备-杭州聚贤气体设备制造有限公司 | 幂简集成 - 品种超全的API接口平台, 一站搜索、试用、集成国内外API接口 | 济南铝方通-济南铝方通价格-济南方通厂家-山东鲁方通建材有限公司 | 【德信自动化】点胶机_全自动点胶机_自动点胶机厂家_塑料热压机_自动螺丝机-深圳市德信自动化设备有限公司 | 球盟会·(中国)官方网站| 3A别墅漆/3A环保漆_广东美涂士建材股份有限公司【官网】 | 长沙广告公司_制作,长沙喷绘_发光字_招牌制作_长沙泓润广告官网 长城人品牌官网 | 撕碎机,撕破机,双轴破碎机-大件垃圾破碎机厂家 | 工控机-图像采集卡-PoE网卡-人工智能-工业主板-深圳朗锐智科 |