js中創(chuàng)建對(duì)象的幾種方式
前言
不管是哪門語(yǔ)言,千變?nèi)f化不離其宗,深入理解其本質(zhì),方能應(yīng)用自如。對(duì)應(yīng)到j(luò)s,閉包,原型,函數(shù),對(duì)象等是需要花費(fèi)大功夫思考、理解的。本文穿插了js原型和函數(shù)的相關(guān)知識(shí),討論了批量創(chuàng)建對(duì)象的幾種方式以及它們的優(yōu)缺點(diǎn)。
正文
說(shuō)起創(chuàng)建對(duì)象,最容易想到的便是通過(guò)對(duì)象字面量方式直接定義一個(gè)對(duì)象吧,但這種方式只能創(chuàng)建少量,單獨(dú)且相互間無(wú)聯(lián)系的對(duì)象。若要批量創(chuàng)建對(duì)象,該如何?
工廠模式
工廠模式非常直觀,將創(chuàng)建對(duì)象的過(guò)程抽象為一個(gè)函數(shù),用函數(shù)封裝以特定接口創(chuàng)建對(duì)象的細(xì)節(jié)。如下所示:
function createStudent(name,sex,grade){
var o = new Object();
o.name = name;
o.sex = sex;
o.grade = grade;
o.sayName = function(){
console.log(this.name);
}
return o;
}
var s1 = createStudent('Claiyre','famale',1);
通俗地講,工廠模式就是將創(chuàng)建對(duì)象的語(yǔ)句放在一個(gè)函數(shù)里,通過(guò)傳入?yún)?shù)來(lái)創(chuàng)建特定對(duì)象,最后返回創(chuàng)建的對(duì)象。
工廠模式雖然可以創(chuàng)建多個(gè)相似的對(duì)象,但卻不能解決對(duì)象標(biāo)識(shí)的問(wèn)題,即怎樣知道一個(gè)對(duì)象的類型。構(gòu)造函數(shù)模式應(yīng)運(yùn)而生。
構(gòu)造函數(shù)模式
構(gòu)造函數(shù)模式是java語(yǔ)言創(chuàng)建對(duì)象的通用方式。兩種語(yǔ)言用構(gòu)造函數(shù)創(chuàng)建對(duì)象的方式略有不同,注意區(qū)別。
在JavaScript中沒(méi)有類的概念,函數(shù)即為一等公民,因此,不必顯式聲明某個(gè)類,直接創(chuàng)建構(gòu)造函數(shù)即可,類的方法和屬性在構(gòu)造函數(shù)中(或原型對(duì)象上)處理。構(gòu)造函數(shù)模式的示例代碼如下:
function Student(name,sex,grade){
this.name = name;
this.sex = sex;
this.grade = grade;
this.sayName = function(){
console.log(this.name);
}
}
var s2 = new Student('孫悟空','male',2);
細(xì)心的朋友一定發(fā)現(xiàn)了構(gòu)造函數(shù)的函數(shù)名首字母是大寫的,而普通函數(shù)首字母則是小寫,這是眾多OO語(yǔ)言約定俗成的規(guī)定,雖然大多數(shù)情況下不大寫也不會(huì)報(bào)錯(cuò),但是為了代碼的規(guī)范性和可讀性,還是應(yīng)該將構(gòu)造函數(shù)的首字母大寫,與普通函數(shù)區(qū)別開(kāi)。
與工廠模式相比,用構(gòu)造模式創(chuàng)建對(duì)象有以下幾點(diǎn)不同:
- 沒(méi)有顯示地創(chuàng)建對(duì)象
- 直接將屬性和方法賦給this對(duì)象
- 沒(méi)有return語(yǔ)句
此外,還應(yīng)注意到要?jiǎng)?chuàng)建Student的實(shí)例,必須要使用new操作符,創(chuàng)建的實(shí)例對(duì)象將有一個(gè)constructor(構(gòu)造器)屬性,指向Person構(gòu)造函數(shù)。調(diào)用構(gòu)造函數(shù)創(chuàng)建對(duì)象經(jīng)過(guò)了以下幾個(gè)過(guò)程:
- 創(chuàng)建一個(gè)新對(duì)象
- 將構(gòu)造函數(shù)的作用域賦給新對(duì)象(因此this就指向了這個(gè)新對(duì)象)
- 執(zhí)行構(gòu)造函數(shù)中的代碼
- 返回新對(duì)象(不需要顯式返回)
構(gòu)造函數(shù)雖好用,但也不是沒(méi)有缺點(diǎn)。使用構(gòu)造函數(shù)的主要問(wèn)題是:每個(gè)方法都要在每個(gè)實(shí)例上創(chuàng)建一遍。在ECMAScript中,函數(shù)即對(duì)象,因此每定義一個(gè)函數(shù),也就是實(shí)例化了一個(gè)對(duì)象。下面的例子證明了這個(gè)缺點(diǎn)。
var s3 = new Student('唐僧','male',3);
var s4 = new Student('白骨精','female',4);
s3.sayName();
s4.sayName();
console.log(s3.sayName == s4.sayName);
運(yùn)行結(jié)果:

也就是說(shuō)通過(guò)構(gòu)造函數(shù)實(shí)例化的多個(gè)對(duì)象的方法,是多個(gè)不同的方法,但它們內(nèi)部的代碼以及實(shí)現(xiàn)的功能是相同的,這就造成了一定的資源浪費(fèi)。
幸運(yùn)的是,這個(gè)問(wèn)題可以用原型模式來(lái)解決。
原型模式
js中,每個(gè)函數(shù)都有一個(gè)prototype屬性,它是一個(gè)指針,指向一個(gè)對(duì)象,叫做原型對(duì)象,原型對(duì)象包含了可以由特定類型的所有實(shí)例對(duì)象共享的屬性和方法。此外,這個(gè)對(duì)象有一個(gè)與生自來(lái)的屬性constructor,指向創(chuàng)建對(duì)象的構(gòu)造方法。
使用原型模式可以讓所有的實(shí)例共享原型對(duì)象中的屬性和方法,也就是說(shuō),不必再構(gòu)造函數(shù)中定義對(duì)象實(shí)例的信息。用代碼表示如下:
function Student_1(){
}
Student_1.prototype.name = 'Claiyre';
Student_1.prototype.sex = 'female';
Student_1.prototype.class = 5;
Student_1.prototype.sayName = function (){
console.log(this.name);
}
var s5 = new Student_1(); s5.sayName(); //Claiyre
var s6 = new Student_1();
s6.sayName(); //Claiyre
一張圖勝過(guò)千言萬(wàn)語(yǔ),下圖清楚地闡釋了各個(gè)對(duì)象和原型對(duì)象間的關(guān)系:

了解過(guò)原型后,可以繼續(xù)在實(shí)例對(duì)象上增添屬性或方法:
s6.name = 'John'; s6.sayName(); //John
當(dāng)要讀取某個(gè)對(duì)象的屬性時(shí),都會(huì)執(zhí)行一次搜索,搜索首先從對(duì)象實(shí)例本身開(kāi)始,如果在實(shí)例中找到了這個(gè)屬性,則搜索結(jié)束,返回實(shí)例屬性的值;若實(shí)例上沒(méi)有找到,則繼續(xù)向?qū)ο蟮脑蛯?duì)象延伸,搜索對(duì)象的原型對(duì)象,若在原型對(duì)象上找到了,則返回原型上相應(yīng)屬性的值,若沒(méi)有找到,則返回undefined。因此,實(shí)例對(duì)象屬性會(huì)覆蓋原型對(duì)象上的同名屬性,所以上面第二行代碼輸出的是John。
- Object.getPrototypeOf(object)方法返回參數(shù)對(duì)象的原型對(duì)象。
- Object.keys(object)方法返回對(duì)象上課枚舉的實(shí)例屬性。
原型中的所有屬性都是被所有實(shí)例所共享的,這種共享對(duì)于函數(shù)來(lái)說(shuō)非常合適,對(duì)于包含基本值的屬性也說(shuō)的過(guò)去(實(shí)例屬性會(huì)覆蓋原型同名屬性),但對(duì)于那些包含引用類型的屬性,可有大麻煩了
Student_1.prototype.friends = ['aa','bb'];
console.log('s6的朋友' + s6.friends);
s5.friends.push('cc');
console.log('s5的朋友' + s5.friends);
console.log('s6的朋友' + s6.friends);
運(yùn)行結(jié)果:

問(wèn)題來(lái)了,我們只想改變s5的朋友列表,但由于原型模式的共享本質(zhì),s6的朋友列表也隨之改變了。
因此,很少單獨(dú)使用原型模式。
組合使用構(gòu)造函數(shù)和原型模式
構(gòu)造函數(shù)模式用于定義實(shí)例屬性,原型模式則用于定義方法和共享的屬性。這種混合模式不僅支持向構(gòu)造函數(shù)傳入?yún)?shù),還最大限度地節(jié)約了內(nèi)存,可謂是集兩模式之長(zhǎng)。示例代碼如下:
function Student(name,sex,grade){
this.name = name;
this.sex = sex;
this.grade = grade;
}
Student.prototype.sayName = function(){
console.log(this.name);
}
Student.prototype.school = 'Joooh school';
其他模式
除了以上幾種常見(jiàn)的模式外,批量創(chuàng)建對(duì)象的方式還有
- 動(dòng)態(tài)原型模式:僅在第一次調(diào)用構(gòu)造函數(shù)時(shí),將方法賦給原型對(duì)象的相應(yīng)屬性,其他示例的處理方式同構(gòu)造函數(shù)模式
- 寄生構(gòu)造函數(shù)模式:僅僅封裝創(chuàng)建對(duì)象的代碼,然后再返回新創(chuàng)建的對(duì)象,仍使用new操作符調(diào)用
- 穩(wěn)妥構(gòu)造函數(shù)模式:沒(méi)有公共屬性,只有私有變量和方法,以及一些get/set方法,用以處理私有變量。
結(jié)語(yǔ)
每種模式都有各自的優(yōu)缺點(diǎn),具體要使用哪種,還需結(jié)合實(shí)際場(chǎng)景,深入理解,靈活運(yùn)用。
以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,同時(shí)也希望多多支持腳本之家!
- JS中的函數(shù)與對(duì)象的創(chuàng)建方式
- JavaScript創(chuàng)建對(duì)象方式總結(jié)【工廠模式、構(gòu)造函數(shù)模式、原型模式等】
- JavaScript創(chuàng)建對(duì)象的常用方式總結(jié)
- JavaScript創(chuàng)建對(duì)象的七種方式(推薦)
- 深入理解JavaScript創(chuàng)建對(duì)象的多種方式以及優(yōu)缺點(diǎn)
- JS對(duì)象創(chuàng)建的幾種方式整理
- 創(chuàng)建一般js對(duì)象的幾種方式
- 詳解js創(chuàng)建對(duì)象的幾種方式和對(duì)象方法
相關(guān)文章
JS 實(shí)現(xiàn)復(fù)制到剪貼板的幾種方式小結(jié)
本文主要介紹了JS 實(shí)現(xiàn)復(fù)制到剪貼板的幾種方式小結(jié),包括ClipboardAPI和document.execCommand這兩種方法,具有一定的參考價(jià)值,感興趣的可以了解一下2025-02-02
JS中的算法與數(shù)據(jù)結(jié)構(gòu)之二叉查找樹(Binary Sort Tree)實(shí)例詳解
這篇文章主要介紹了JS中的算法與數(shù)據(jù)結(jié)構(gòu)之二叉查找樹(Binary Sort Tree),結(jié)合實(shí)例形式詳細(xì)分析了二叉查找樹(Binary Sort Tree)的原理、定義、遍歷、查找、插入、刪除等常見(jiàn)操作技巧,需要的朋友可以參考下2019-08-08
詳解JavaScript如何實(shí)現(xiàn)并發(fā)控制的Promise隊(duì)列調(diào)度器
Promise是JavaScript中一種處理異步操作的技術(shù),提供了一種更優(yōu)雅的方式來(lái)處理并發(fā)任務(wù)和串行化操作,本文主要介紹了實(shí)現(xiàn)并發(fā)控制的Promise隊(duì)列調(diào)度器的方法,需要的可以參考一下2023-07-07
JavaScript數(shù)組的定義及數(shù)字操作技巧
這篇文章主要介紹了JavaScript數(shù)組的定義及數(shù)字操作技巧的相關(guān)資料,需要的朋友可以參考下2016-06-06
淺談JavaScript中的String對(duì)象常用方法
這篇文章主要介紹了JavaScript中的String對(duì)象常用方法,非常簡(jiǎn)單實(shí)用,有需要的小伙伴參考下2015-02-02
JavaScript中值類型與引用類型實(shí)例說(shuō)明
JavaScript中值類型與引用類型說(shuō)明,需要的朋友可以參考下。2010-12-12
JavaScript中數(shù)據(jù)結(jié)構(gòu)與算法(二):隊(duì)列
這篇文章主要介紹了JavaScript中數(shù)據(jù)結(jié)構(gòu)與算法(二):隊(duì)列,隊(duì)列是只允許在一端進(jìn)行插入操作,另一個(gè)進(jìn)行刪除操作的線性表,隊(duì)列是一種先進(jìn)先出(First-In-First-Out,F(xiàn)IFO)的數(shù)據(jù)結(jié)構(gòu),需要的朋友可以參考下2015-06-06

