摘要:前言雖然使用構(gòu)造函數(shù)或者使用對(duì)象字面量可以很方便的用來(lái)創(chuàng)建一個(gè)對(duì)象,但這種方式有一個(gè)明顯的缺點(diǎn)使用一個(gè)接口創(chuàng)建多個(gè)對(duì)象會(huì)產(chǎn)生很多冗余的代碼。即調(diào)用構(gòu)造函數(shù)所創(chuàng)建的那個(gè)對(duì)象的原型對(duì)象好處是可以讓所有對(duì)象的實(shí)例共享他的屬性的方法。
前言
雖然使用Object構(gòu)造函數(shù)或者使用對(duì)象字面量可以很方便的用來(lái)創(chuàng)建一個(gè)對(duì)象,但這種方式有一個(gè)明顯的缺點(diǎn):使用一個(gè)接口創(chuàng)建多個(gè)對(duì)象會(huì)產(chǎn)生很多冗余的代碼。因此為了解決這個(gè)問(wèn)題,人們開(kāi)始使用以下幾種方式來(lái)常見(jiàn)對(duì)象。
工廠(chǎng)模式該模式抽象了創(chuàng)建對(duì)象的具體過(guò)程,用函數(shù)來(lái)以特定接口創(chuàng)建對(duì)象的細(xì)節(jié)
function cPerson(name,sex,age){ var o = new Object(); o.name = name; o.sex = sex; o.age = age; o.show = function(){ console.log(this.name,this.age,this.sex); } return o; } var p1 = cPerson("謙龍","男","100"); p1.show(); var p2 = cPerson("雛田","女","14"); p2.show();
工廠(chǎng)模式測(cè)試
工廠(chǎng)方式的問(wèn)題:使用工廠(chǎng)模式能夠創(chuàng)建一個(gè)包含所有信息的對(duì)象,可以無(wú)數(shù)次的調(diào)用的這個(gè)函數(shù)。雖然其解決了創(chuàng)建多個(gè)相似對(duì)象的問(wèn)題,但卻沒(méi)有解決對(duì)象識(shí)別的問(wèn)題(即如何得知一個(gè)對(duì)象的類(lèi)型)
function CPerson(name,sex,age) {//注意這里 構(gòu)造函數(shù)首字母大寫(xiě) this.name = name; this.sex = sex; this.age = age; this.show = function () { console.log(this.name, this.age, this.sex); } } var p1 = new CPerson("謙龍","男","100"); p1.show(); var p2 = new CPerson("雛田","女","14"); p2.show();
構(gòu)造函數(shù)模式測(cè)試
注意構(gòu)造函數(shù)與工廠(chǎng)模式有些不同的地方,如下
構(gòu)造函數(shù)首字母大寫(xiě)
沒(méi)有顯式地創(chuàng)建對(duì)象
將屬性和方法賦值給了 this對(duì)象
沒(méi)有return語(yǔ)句
而且以這種方式來(lái)調(diào)用構(gòu)造函數(shù)會(huì)大致經(jīng)歷一下幾個(gè)步驟
創(chuàng)建一個(gè)新的對(duì)象
將構(gòu)造函數(shù)的作用域賦值給這個(gè)對(duì)象(因此this就指向了這個(gè)對(duì)象)
執(zhí)行構(gòu)造函數(shù)中的代碼(即給新對(duì)象添加屬性和方法的過(guò)程)
返回對(duì)象
注意:構(gòu)造函數(shù)其實(shí)和普通的函數(shù)沒(méi)有太大的差別,唯一的不同在于調(diào)用方式的不同。以下演示不同的幾種調(diào)用方式
// 調(diào)用方式1 new 方式 var p1 = new CPerson("謙龍","男","100"); p1.show();//謙龍 100 男 // 調(diào)用方式2 普通函數(shù)調(diào)用 CPerson("謙龍","男","100"); window.show()//謙龍 100 男 注意屬性和方法會(huì)被設(shè)置到window對(duì)象上 // 調(diào)用方式3 在另一個(gè)對(duì)象的作用域中調(diào)用 var obj = new Object(); CPerson.call(obj,"謙龍","男","100"); obj.show(); //謙龍 100 男 在obj的作用域
構(gòu)造函數(shù)的問(wèn)題:使用構(gòu)造函數(shù)最主要的問(wèn)題就是每個(gè)方法都要在每個(gè)實(shí)例上重新創(chuàng)建一次,p1與p2的都有show方法,但不是同一個(gè)Function的實(shí)例,因?yàn)閒unction在js中也是一個(gè)對(duì)象。因此他們共有的show方法并不相等。
原型模式每個(gè)函數(shù)都有一個(gè)prototype屬性,這個(gè)屬性是一個(gè)指針,指向一個(gè)對(duì)象。而這個(gè)對(duì)象的用途是 包含可以由特定類(lèi)型的所有實(shí)例 共享的屬性和方法。即調(diào)用構(gòu)造函數(shù)所創(chuàng)建的那個(gè)對(duì)象的 原型對(duì)象
好處是可以讓所有對(duì)象的實(shí)例共享他的屬性的方法。即無(wú)需在構(gòu)造函數(shù)中定義實(shí)例的信息
function CPerson(){ } CPerson.prototype.name="謙龍"; CPerson.prototype.sex="男"; CPerson.prototype.age=100; CPerson.prototype.show=function(){ console.log(this.name, this.age, this.sex); } var p1 = new CPerson(); p1.show(); //謙龍 100 男 var p2 = new CPerson(); p2.show();//謙龍 100 男 console.log(p1.show == p2.show)//true
原型模式測(cè)試
由上圖可知p1與p2共享屬性和方法
原型模式的問(wèn)題:
省略了為構(gòu)造函數(shù)傳遞初始化參數(shù),導(dǎo)致默認(rèn)情況下所有實(shí)例將得到相同的屬性值
所有屬性都會(huì)被實(shí)例所共享,當(dāng)屬性的類(lèi)型是引用類(lèi)型的時(shí)候會(huì)出一定的問(wèn)題,實(shí)例間對(duì)該屬性的修改會(huì)相互影響
針對(duì)以上所說(shuō)的第二個(gè)問(wèn)題我們給出實(shí)例
function CPerson(){ } CPerson.prototype.name="謙龍"; CPerson.prototype.sex="男"; CPerson.prototype.age=100; CPerson.prototype.job=["前端","后端"]; CPerson.prototype.show=function(){ console.log(this.name, this.age, this.sex); } var p1 = new CPerson(); p1.job.push("測(cè)試"); console.log(p1.job);//["前端", "后端", "測(cè)試"] var p2 = new CPerson(); console.log(p2.job);//["前端", "后端", "測(cè)試"] console.log(p1.job == p2.job);// true
測(cè)試
由以上可以看出,兩個(gè)對(duì)象p1,p2對(duì)job的修改會(huì)相互影響,但按照正常思維,實(shí)例一般要有自己的全部的屬性。
組合使用構(gòu)造函數(shù)和原型模式該方式利用構(gòu)造函數(shù)定義實(shí)例屬性、利用原型定義方法和共享的屬性,結(jié)果每個(gè)實(shí)例都有一份實(shí)例屬性的副本,而且共享著方法的引用,可謂是集兩家之所長(zhǎng)。
function CPerson(name,sex,age) {//注意這里 構(gòu)造函數(shù)首字母大寫(xiě) this.name = name; this.sex = sex; this.age = age; this.job=["前端","后端"]; } CPerson.prototype={ constructor:CPerson,//注意這里 show : function () { console.log(this.name, this.age, this.sex); } } var p1 = new CPerson("謙龍","男",100); var p2 = new CPerson("雛田","女",20); p1.job.push("測(cè)試"); console.log(p1.job);//["前端", "后端", "測(cè)試"] console.log(p2.job);//["前端", "后端"] console.log(p1.job == p2.job);//fasle console.log(p1.show == p2.show);//true
組合模式測(cè)試
說(shuō)明:這種組合模式是使用最廣泛、認(rèn)同度最高的一種創(chuàng)建自定義類(lèi)型的方法。
動(dòng)態(tài)原型模式動(dòng)態(tài)原型模式將所有的信息都封裝在了函數(shù)中,而通過(guò)構(gòu)造函數(shù)中初始化原型,保持了同時(shí)使用構(gòu)造函數(shù)和原型的優(yōu)點(diǎn)
function CPerson(name,sex,age) {//注意這里 構(gòu)造函數(shù)首字母大寫(xiě) this.name = name; this.sex = sex; this.age = age; this.job=["前端","后端"]; if(typeof this.show !="function"){ //注意這里 console.log("just one"); CPerson.prototype.show=function(){ console.log(this.name, this.age, this.sex); } } } var p1 = new CPerson("謙龍","男",100); //just one var p2 = new CPerson("雛田","女",20);//沒(méi)有輸出
動(dòng)態(tài)原型模式測(cè)試
該方式的基本思想是創(chuàng)建一個(gè)函數(shù),用來(lái)封裝創(chuàng)建對(duì)象的代碼,然后再返回新創(chuàng)建的對(duì)象。構(gòu)造函數(shù)在不返回值的情況下,默認(rèn)會(huì)返回新對(duì)象的實(shí)例,而通過(guò)return語(yǔ)句可以修改調(diào)用構(gòu)造函數(shù)時(shí)的返回值。
該方式有一定的應(yīng)用場(chǎng)景比如,當(dāng)我們想創(chuàng)建一個(gè)具有額外方法的數(shù)組而又不能修改Array構(gòu)造函數(shù)的情況下,可以使用這種模式
function MyOwnArray(){ var arr=new Array();//創(chuàng)建新對(duì)象 arr.push.apply(arr,arguments); arr.show=function(){ console.log(this.join("|")); } return arr; } var arr1 = new MyOwnArray("謙龍","男",100); arr1.show();
寄生構(gòu)造函數(shù)模式測(cè)試
穩(wěn)妥對(duì)象即沒(méi)有公共屬性,方法也不引用this對(duì)象,穩(wěn)妥對(duì)象最適合在一些安全的環(huán)境中(例如禁止使用this和new)或者防止數(shù)據(jù)被其他應(yīng)用程序修改的時(shí)候使用。
注意:穩(wěn)妥構(gòu)造函數(shù)和寄生式構(gòu)造函數(shù)有許多類(lèi)似的地方,以下是他們的不同之處
不使用new操作符來(lái)調(diào)用構(gòu)造函數(shù)
創(chuàng)建對(duì)象的實(shí)例方法不使用this對(duì)象
function CPerson(name,sex,age){ var obj = new Object(); // private members var myOwnName="謙龍"; obj.showOwnName=function(){ console.log(myOwnName);//只有通過(guò)該方法才能訪(fǎng)問(wèn)myOwnName 私有屬性 } obj.show=function(){ console.log(name,sex,age); } return obj; } var p1=CPerson("謙龍","男","100"); p1.show(); p1.showOwnName();
穩(wěn)妥構(gòu)造函數(shù)模式測(cè)試
除了通過(guò)調(diào)用對(duì)應(yīng)的方法來(lái)訪(fǎng)問(wèn)其數(shù)據(jù)成員,沒(méi)有別的方法可以訪(fǎng)問(wèn)到原始添加的數(shù)據(jù),其提供的這種安全機(jī)制適合在例如ADsafe等的環(huán)境下使用
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/86157.html
摘要:中的對(duì)象無(wú)序的屬性的集合,屬性可以包含基本值對(duì)象函數(shù)。共有四個(gè)描述其行為的特性。返回的是一個(gè)對(duì)象,如果是數(shù)據(jù)屬性,則返回的屬性有如果是訪(fǎng)問(wèn)器屬性則返回的屬性有對(duì)象遍歷函數(shù)數(shù)據(jù)屬性訪(fǎng)問(wèn)器屬性測(cè)試 前言 基于類(lèi)的對(duì)象:我們都知道面向?qū)ο蟮恼Z(yǔ)言中有一個(gè)明顯的標(biāo)志,就是都有類(lèi)的概念,通過(guò)類(lèi)這個(gè)類(lèi)似模板的東西我們可以創(chuàng)建許多個(gè)具有相同的屬性和方法的對(duì)象。然而在ECMAScript中并沒(méi)有類(lèi)的概...
摘要:有需要還可以修改指向謙龍寄生組合式繼承思路是通過(guò)借用構(gòu)造函數(shù)來(lái)繼承屬性,通過(guò)原型鏈的混合形式來(lái)繼承方法改變執(zhí)行環(huán)境實(shí)現(xiàn)繼承有需要還可以修改指向謙龍謙龍拷貝繼承該方法思路是將另外一個(gè)對(duì)象的屬性和方法拷貝至另一個(gè)對(duì)象使用遞歸 前言 js中實(shí)現(xiàn)繼承的方式只支持實(shí)現(xiàn)繼承,即繼承實(shí)際的方法,而實(shí)現(xiàn)繼承主要是依靠原型鏈來(lái)完成的。 原型鏈?zhǔn)嚼^承 該方式實(shí)現(xiàn)的本質(zhì)是重寫(xiě)原型對(duì)象,代之以一個(gè)新類(lèi)型的實(shí)例...
摘要:及相關(guān)問(wèn)題數(shù)據(jù)類(lèi)型函數(shù)中指向原型作用域閉包面向?qū)ο髮?duì)象創(chuàng)建模式繼承嚴(yán)格模式與對(duì)象轉(zhuǎn)換的方法添加屬性,根據(jù)原型創(chuàng)建區(qū)別新特性解構(gòu)賦值簡(jiǎn)化對(duì)象寫(xiě)法剪頭函數(shù)三點(diǎn)運(yùn)算符模板字符串形參默認(rèn)值異步過(guò)程深拷貝與淺拷貝賦值與淺拷貝的區(qū)別淺拷貝的幾種方法實(shí)現(xiàn) js及es相關(guān)問(wèn)題 數(shù)據(jù)類(lèi)型函數(shù)中this指向——————原型作用域閉包——————面向?qū)ο髮?duì)象創(chuàng)建模式繼承——————Es5嚴(yán)格模式Json與j...
摘要:及相關(guān)問(wèn)題數(shù)據(jù)類(lèi)型函數(shù)中指向原型作用域閉包面向?qū)ο髮?duì)象創(chuàng)建模式繼承嚴(yán)格模式與對(duì)象轉(zhuǎn)換的方法添加屬性,根據(jù)原型創(chuàng)建區(qū)別新特性解構(gòu)賦值簡(jiǎn)化對(duì)象寫(xiě)法剪頭函數(shù)三點(diǎn)運(yùn)算符模板字符串形參默認(rèn)值異步過(guò)程深拷貝與淺拷貝賦值與淺拷貝的區(qū)別淺拷貝的幾種方法實(shí)現(xiàn) js及es相關(guān)問(wèn)題 數(shù)據(jù)類(lèi)型函數(shù)中this指向——————原型作用域閉包——————面向?qū)ο髮?duì)象創(chuàng)建模式繼承——————Es5嚴(yán)格模式Json與j...
閱讀 1812·2023-04-25 16:28
閱讀 760·2021-11-23 09:51
閱讀 1533·2019-08-30 15:54
閱讀 1225·2019-08-30 15:53
閱讀 2900·2019-08-30 15:53
閱讀 3485·2019-08-30 15:43
閱讀 3329·2019-08-30 11:18
閱讀 3392·2019-08-26 10:25