一文詳解JavaScript中使用對象數(shù)組、對象(字典)保存數(shù)據(jù)的區(qū)別
示例:
const products=[
{id:'aaa',name:'aname',overview:'aoverview'},
{id:'bbb',name:'bname',overview:'boverview'}
];
const products={
'aaa':{name:'aname',overview:'aoverview'},
'bbb':{name:'bname',overview:'boverview'}
};在 JavaScript 中存儲產(chǎn)品數(shù)據(jù),你給出的兩種方案分別使用了數(shù)組和對象(字典)。下面從多個角度分析它們的優(yōu)劣、運行效率以及底層機制,以便你根據(jù)實際需求做出選擇。
1. 數(shù)據(jù)結構概覽
// 方案一:數(shù)組
const productsArray = [
{ id: 'aaa', name: 'aname', overview: 'aoverview' },
{ id: 'bbb', name: 'bname', overview: 'boverview' }
];
// 方案二:對象(以 id 為鍵)
const productsObject = {
'aaa': { name: 'aname', overview: 'aoverview' },
'bbb': { name: 'bname', overview: 'boverview' }
};
2. 核心操作對比
| 操作 | 數(shù)組(productsArray) | 對象(productsObject) |
|---|---|---|
| 通過 id 查找 | 需要遍歷數(shù)組,時間復雜度 O(n) arr.find(p => p.id === id) | 直接通過鍵訪問,時間復雜度 O(1) obj[id] |
| 遍歷所有產(chǎn)品 | 直接使用 for、forEach 或 map,內(nèi)存連續(xù),速度快 | 需先獲取 Object.values(obj) 或 Object.keys(obj),產(chǎn)生臨時數(shù)組,稍慢 |
| 添加新產(chǎn)品 | push 在末尾追加,O(1)(無需移動元素) | 直接賦值 obj[newId] = {...},O(1)(哈希表插入) |
| 刪除產(chǎn)品 | 若需保持順序,用 splice 會移動后續(xù)元素,O(n) 若不關心順序,可標記刪除 | 使用 delete obj[id],O(1),但可能導致對象進入“慢模式” |
| 更新產(chǎn)品 | 先查找(O(n))再修改,或直接通過已知索引修改(O(1)) | 直接通過鍵修改 obj[id].name = 'new',O(1) |
| 按 id 排序/篩選 | 可直接用數(shù)組方法(sort, filter),方便靈活 | 需先轉(zhuǎn)為數(shù)組,再操作 |
3. 內(nèi)存占用
- 數(shù)組:每個元素都是一個對象,且內(nèi)部必須顯式存儲
id字段。如果有 N 個產(chǎn)品,就會存儲 N 個 id 字符串。 - 對象:id 作為鍵(key)存儲,值對象中不再需要
id字段。因此節(jié)省了 N 個 id 字符串的內(nèi)存(但鍵本身也占用內(nèi)存,通常比字符串值稍少,因為鍵被內(nèi)部化)。
總體而言,對象方案在內(nèi)存上略優(yōu),尤其當數(shù)據(jù)量較大時差異更明顯。
4. JavaScript 引擎內(nèi)部運作方式
數(shù)組(以 V8 引擎為例)
- 如果數(shù)組元素類型一致(例如都是對象),V8 會使用 PACKED_ELEMENTS 模式,元素在內(nèi)存中連續(xù)存儲,訪問和迭代非常快,CPU 緩存利用率高。
- 當數(shù)組長度變化(如
splice刪除中間元素),需要移動后續(xù)元素,開銷較大。 - 引擎還會根據(jù)元素類型優(yōu)化(如數(shù)字數(shù)組會用 C 語言級別的數(shù)組存儲),但這里存儲的是對象引用,所以仍是引用數(shù)組。
對象(字典)
V8 中對象有兩種表示模式:
- 快速屬性:當對象屬性數(shù)量較少、且屬性名是確定的字符串時,V8 會使用隱藏類(Hidden Class)和內(nèi)聯(lián)緩存(Inline Cache),屬性訪問接近 C 語言結構體的速度。
- 慢速屬性(字典模式):當屬性被頻繁動態(tài)添加/刪除,或數(shù)量很多時,V8 會將對象切換為哈希表實現(xiàn),此時訪問速度仍然 O(1),但常數(shù)因子較大,且內(nèi)存占用增加。
你的 productsObject 鍵是動態(tài)的(每個產(chǎn)品 id 都可能不同),且數(shù)量可能較多,很可能最終以哈希表形式存儲。但通過 id 訪問依然非常快。
5. 實際使用中的優(yōu)劣總結
方案一:數(shù)組
優(yōu)點:
- 保持順序(按插入順序或排序后順序),適合列表展示。
- 遍歷方便,可直接用數(shù)組迭代方法。
- 與 React/Vue 等框架的列表渲染完美配合(通常需要傳遞數(shù)組)。
缺點:
- 通過 id 查找效率低(需要遍歷或額外建立索引)。
- 刪除中間元素成本高(
splice移動元素)。
方案二:對象
優(yōu)點:
- 通過 id 查找、更新、刪除極快(O(1))。
- 內(nèi)存稍?。o需重復存 id)。
- 天然保證 id 唯一性(鍵不能重復)。
缺點:
- 沒有順序保證(ES6 之后對象鍵按創(chuàng)建順序枚舉,但刪除再添加可能影響順序)。
- 遍歷需要先轉(zhuǎn)換(
Object.values),且轉(zhuǎn)換結果是一個新數(shù)組,頻繁遍歷可能產(chǎn)生臨時對象開銷。 - 不能直接使用數(shù)組方法(如
map,filter)。
6. 常見優(yōu)化實踐
在實際開發(fā)中,經(jīng)常需要兼顧快速查找和順序遍歷。這時可以采用復合結構:
const productsList = []; // 用于順序展示
const productsMap = {}; // 用于快速查找
// 添加產(chǎn)品
function addProduct(product) {
productsList.push(product);
productsMap[product.id] = product;
}
// 通過 id 查找
function getProduct(id) {
return productsMap[id];
}
// 刪除產(chǎn)品(假設不關心順序,用 filter 重建列表)
function deleteProduct(id) {
productsList = productsList.filter(p => p.id !== id);
delete productsMap[id];
}
這種方式結合了兩者的優(yōu)點,但需要維護兩個結構的一致性。
7. 如何選擇
如果你的應用主要場景是:
- 根據(jù) id 頻繁查找、更新(如購物車、商品詳情頁) → 選對象
- 展示產(chǎn)品列表、排序、過濾(如后臺管理列表) → 選數(shù)組
- 兩者都很重要 → 考慮復合結構
數(shù)據(jù)量大小:如果數(shù)據(jù)量很?。◣资畻l),兩種方案性能差異可以忽略,選你寫起來更方便的即可。
是否需要保持順序:如果需要按特定順序展示(如按添加時間),數(shù)組更合適;如果順序不重要,對象也能滿足。
8. 內(nèi)部機制延伸理解
數(shù)組查找為什么慢?因為數(shù)組本身沒有建立 id 到索引的映射,每次查找都必須遍歷所有元素,直到找到匹配的 id。如果數(shù)組很大,這個開銷會線性增長。
對象鍵訪問為什么快?對象在內(nèi)存中通過哈希函數(shù)將鍵映射到存儲位置,平均只需一次計算就能定位到值,無論對象中有多少屬性(理想情況下)。
delete 操作的影響delete obj[key] 會在對象中留下一個“空洞”,如果對象之前處于快速模式,可能會觸發(fā)引擎將其降級為慢速字典模式,后續(xù)屬性訪問性能下降。因此,如果頻繁刪除并重新添加大量屬性,建議用 undefined 標記或改用 Map(Map 專門為頻繁增刪設計,性能更好)。
總結
兩種方案各有優(yōu)劣,沒有絕對的好壞。理解它們的底層行為后,你可以根據(jù)業(yè)務場景的讀寫比例、是否強調(diào)順序、數(shù)據(jù)量級來靈活選擇。在大多數(shù)中大型應用中,對象(或 Map)用于快速查找,數(shù)組用于列表渲染是常見模式。
到此這篇關于一文詳解JavaScript中使用對象數(shù)組、對象(字典)保存數(shù)據(jù)的區(qū)別的文章就介紹到這了,更多相關JavaScript存儲數(shù)據(jù)方法對比內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
js實現(xiàn)動態(tài)加載數(shù)據(jù)瀑布流
這篇文章主要為大家詳細介紹了js實現(xiàn)動態(tài)加載數(shù)據(jù)瀑布流,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-07-07
Javascript highcharts 餅圖顯示數(shù)量和百分比實例代碼
這篇文章主要介紹了Javascript highcharts 餅圖顯示數(shù)量和百分比實例代碼的相關資料,這里附有實例代碼,需要的朋友可以參考下2016-12-12
layui 實現(xiàn)table翻頁滾動條位置保持不變的例子
今天小編就為大家分享一篇layui 實現(xiàn)table翻頁滾動條位置保持不變的例子,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-09-09

