JS創(chuàng)建對(duì)象的六種方式
1.對(duì)象字面量(Object Literal)
用法: 直接通過{}定義對(duì)象,是最簡單的方式;
原理: 直接分配內(nèi)存創(chuàng)建一個(gè)普通對(duì)象,繼承object.prototype;
- 直接內(nèi)存分配: 當(dāng)使用{}定義對(duì)象時(shí),js引擎會(huì)直接在堆內(nèi)存中分配一個(gè)普通對(duì)象。
- 隱藏原型繼承: 該對(duì)象的[[Prototype]](即 proto) 會(huì)自動(dòng)指向 Object.prototype, 繼承原始對(duì)象默認(rèn)方法 (如:toString).
- 屬性初始化: 字面量中的屬性和方法會(huì)直接掛載到對(duì)象自身,而非原型鏈。
例子:
const person {
name: '小明',
age: 25,
greet() {
console.log(`hi , i'm ${this.name}`)
}
}
person.greet() //hi ,i'm 小明
const obj = {key:“value”};
//等價(jià)于:
const obj = new Object(); //隱式調(diào)用 Object 構(gòu)造函數(shù)
obj.key = "value";
特點(diǎn):
- 適合創(chuàng)建單例對(duì)象或一次性對(duì)象;
- 所有屬性方法均為實(shí)例自身成員,無法共享
2.構(gòu)造函數(shù)(constructor function)
用法:通過 new 關(guān)鍵字調(diào)用構(gòu)造函數(shù)創(chuàng)建對(duì)象
原理: new 操作
- 1.創(chuàng)建空對(duì)象: 在內(nèi)存中創(chuàng)建一個(gè)新對(duì)象 {}
- 2.綁定原型:將新對(duì)象的[[Prototype]] 即原型鏈, 指向構(gòu)造函數(shù)的prototype屬性
- 3.執(zhí)行構(gòu)造函數(shù):將構(gòu)造函數(shù)內(nèi)的this指向新對(duì)象,執(zhí)行構(gòu)造函數(shù)代碼(初始化屬性)
- 4.返回對(duì)象: 若構(gòu)造函數(shù)未顯示返回其他對(duì)象,則返回新對(duì)象;
例子:
function person(name, age){
// this = {}; (隱式操作)
// this.__proto__ = person.prototype; (隱式操作)
this.name = name;
this.age = age;
this.greet = function(){
console.log(`hi, i'm ${this.name}`)
}
// return this; (隱式操作)
}
const xiaoming = new person('小明', 25);
xiaoming.greet(); //hi, i'm 小明
//原型鏈結(jié)構(gòu): xiaoming.__proto__ -> person.prototype -> Object.prototype -> null;
缺點(diǎn):每個(gè)實(shí)例的方法都是獨(dú)立的,浪費(fèi)內(nèi)存(可以優(yōu)化共享原型方法);
- 若方法定義在構(gòu)造函數(shù)內(nèi)部,每個(gè)實(shí)例會(huì)有獨(dú)立的方法副本(浪費(fèi)內(nèi)存);
- 若方法定義在person.prototype上,所有實(shí)例共享同一方法(推薦做法)
3. Object.create()
用法:基于現(xiàn)有對(duì)象作為原型創(chuàng)建新對(duì)象。
原理:創(chuàng)建一個(gè)新對(duì)象,并將其Prototype 指向傳入的對(duì)象;
- 顯式原型繼承:直接創(chuàng)建一個(gè)新對(duì)象,并手動(dòng)指定其[[Prototype]] 即:原型鏈 __ proto __
- 參數(shù)處理: 1.若傳入null, 新對(duì)象的[[Prototype]]為null (無原型鏈); 2.若傳入對(duì)象proto, 新對(duì)象繼承proto的屬性和方法;
例子:
const prototypeObj = {
greet(){
console.log(`hi, i'm ${this.name}`)
}
}
const person = Object.create(prototypeObj);
person.name = "小明";
person.age = 10;
person.greet(); //hi , i'm 小明
擴(kuò)展:可創(chuàng)建無原型的對(duì)象(Object.create(null)),適合純粹的數(shù)據(jù)存儲(chǔ);
4.工廠函數(shù)(Factory Function)
用法: 封裝對(duì)象創(chuàng)建邏輯的函數(shù),直接返回新對(duì)象;
原理:手動(dòng)創(chuàng)建對(duì)象并返回,不依賴 new 或原型鏈;
- 封裝對(duì)象創(chuàng)建: 通過普通函數(shù)返回新對(duì)象,不依賴new或者原型鏈。
- 獨(dú)立實(shí)例: 每次調(diào)用工廠函數(shù)都會(huì)產(chǎn)生新的對(duì)象,所有屬性和方法均為實(shí)例自身成員。
例子:
function createPeason(name,age){
const obj = {}; //顯示創(chuàng)建對(duì)象
obj.name = name;
obj.age = age;
obj.greet = function(){} //方法不共享
return obj;
}
const xiaoming = createPeason('小明',10);
xiaoming.greet(); //hi, i'm 小明;
特點(diǎn):避免 new 的使用,但方法無法共享(每個(gè)實(shí)例的方法獨(dú)立)。
對(duì)比構(gòu)造函數(shù):
- 優(yōu)勢(shì): 更直觀,避免new 的依賴。
- 劣勢(shì): 方法無法共享,內(nèi)存效率低。 (因?yàn)槭情]包?。?/li>
5.ES6 class 語法
用法:使用clase關(guān)鍵字定義類,通過new實(shí)例化;
原理:本質(zhì)是構(gòu)造函數(shù)的語法糖(構(gòu)造函數(shù)另一種寫法),基于原型鏈實(shí)現(xiàn)繼承。
- 方法掛載: 類中定義的方法會(huì)自動(dòng)添加到prototype對(duì)象上,實(shí)現(xiàn)共享;
- 繼承機(jī)制: extends 關(guān)鍵字通過修改原型鏈實(shí)現(xiàn)繼承(子類的prototype 指向父類實(shí)例)
例子:
class Person {
construtor(name,age){
this.name = name;
this.age = age;
}
greet(){
console.log(`hi, i'm ${this.name}`)
}
}
const xiaoming = new Person('小明',10);
xiaoming.greet(); // hi, i'm 小明;
//原型鏈結(jié)構(gòu): xiaoming.__proto__ -> Person.prototype -> Object.prototyle -> null;
優(yōu)點(diǎn): 語法更清晰,支持繼承(extends)和靜態(tài)方法(static)
6.單例模式(Singleton)
用法:確保一個(gè)類只有一個(gè)實(shí)例;
原理:通過閉包或模塊化限制實(shí)例化次數(shù)
- 閉包封裝: 通過立即執(zhí)行函數(shù)(iife)和閉包保存唯一實(shí)例的引用。
- 惰性初始化: 在首次調(diào)用時(shí)創(chuàng)建實(shí)例,后續(xù)調(diào)用直接返回已存在的實(shí)例;
例子:
const singleton - (function(){
let instance;
function createInstance() {
return { id: Math.random() };
}
return {
getInstance(){
if(!instance) instance = createInstance();
return instance;
}
}
})();
const obj1 = singleton.getInstance();
const obj2 = singleton.getInstance();
console.log(obj1 === obj2); //true
匯總 - 總結(jié)對(duì)比
| 方式 | 特點(diǎn) | 適用場景 |
|---|---|---|
| 對(duì)象字面量 | 簡單直接,適合一次性對(duì)象 | 簡單數(shù)據(jù)存儲(chǔ)、配置項(xiàng) |
| 構(gòu)造函數(shù) | 可復(fù)用,但方法定義在原型上 節(jié)省內(nèi)存 | 需要多個(gè)相似實(shí)例 |
| Object.create() | 靈活控制原型鏈,可創(chuàng)建無原型的對(duì)象 | 原型繼承、純凈對(duì)象 |
| 工廠函數(shù) | 避免 new, 但方法無法共享 | 簡單對(duì)象生活 |
| class | 語法清晰,支持繼承 | 面向?qū)ο箝_發(fā) |
| 單例模式 | 全局唯一實(shí)例 | 全局狀態(tài)管理 |
選擇建議:
- 簡單對(duì)象: 優(yōu)先用對(duì)象字面量或者工廠函數(shù)。
- 復(fù)用和繼承: 使用class或構(gòu)造函數(shù)。
- 原型控制: 使用Object.create()。
- 全局唯一: 單例模式。
以上就是JS創(chuàng)建對(duì)象的六種方式的詳細(xì)內(nèi)容,更多關(guān)于JS創(chuàng)建對(duì)象的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
TypeScript中的類型斷言[as語法|<>語法]的使用
本文主要介紹了TypeScript中的類型斷言[as語法|<>語法]的使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06
使用Three.js?實(shí)現(xiàn)虎年春節(jié)3D創(chuàng)意頁面
虎年春節(jié)將至,本文使用?React?+?Three.js技術(shù)棧,實(shí)現(xiàn)趣味?3D創(chuàng)意頁面,主要包括:ShadowMaterial、?MeshPhongMaterial等基本材質(zhì)的使用、使用?LoadingManager展示模型加載進(jìn)度、OrbitControls`的緩動(dòng)動(dòng)畫、TWEEN簡單補(bǔ)間動(dòng)畫效果等,感興趣的朋友一起看看吧2022-01-01
微信小程序滑動(dòng)選擇器的實(shí)現(xiàn)代碼
這篇文章主要介紹了微信小程序滑動(dòng)選擇器的實(shí)現(xiàn)代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-08-08
如何從JavaScript數(shù)組中刪除空對(duì)象
JS中數(shù)組是我們較為常用的一種數(shù)據(jù)結(jié)構(gòu),下面這篇文章主要給大家介紹了關(guān)于如何從JavaScript數(shù)組中刪除空對(duì)象的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-05-05
js實(shí)現(xiàn)刷新頁面后回到記錄時(shí)滾動(dòng)條的位置【兩種方案可選】
本文主要介紹了頁面的div中有滾動(dòng)條,js實(shí)現(xiàn)刷新頁面后回到記錄時(shí)滾動(dòng)條的位置的兩種方案,需要的朋友可以看下2016-12-12
詳解JavaScript實(shí)現(xiàn)動(dòng)態(tài)的輪播圖效果
這篇文章主要介紹了JavaScript實(shí)現(xiàn)動(dòng)態(tài)的輪播圖效果,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
js獲取本機(jī)的外網(wǎng)/廣域網(wǎng)ip地址完整源碼
通過js獲取本機(jī)的外網(wǎng)和廣域網(wǎng)ip地址的方法有很多,本文為大家介紹個(gè)不錯(cuò)的方法,希望對(duì)大家有所幫助2013-08-08
JavaScript監(jiān)聽文本框回車事件并過濾文本框空格的方法
這篇文章主要介紹了JavaScript監(jiān)聽文本框回車事件并過濾文本框空格的方法,涉及javascript操作文本框獲取、清空及刪除空格的技巧,需要的朋友可以參考下2015-04-04

