為什么前端開(kāi)發(fā)者都用 Set 代替 Array 去重?實(shí)測(cè)性能對(duì)比
數(shù)組去重是JavaScript中的一個(gè)常見(jiàn)的操作,隨著ES6的普及,越來(lái)越多的前端開(kāi)發(fā)者拋棄了傳統(tǒng)的Array去重方法,轉(zhuǎn)而使用Set來(lái)完成這項(xiàng)任務(wù)。這種轉(zhuǎn)變不僅僅是因?yàn)榇a更簡(jiǎn)潔,更重要的是性能上的巨大差異。

一、Set去重的簡(jiǎn)潔寫法
在ES6出現(xiàn)之前,數(shù)組去重通常需要編寫循環(huán)和條件判斷:
function uniqueArray(arr) {
const result = [];
for (let i = 0; i < arr.length; i++) {
    if (result.indexOf(arr[i]) === -1) {
      result.push(arr[i]);
    }
  }
return result;
}
// 使用
const array = [1, 2, 3, 3, 4, 4, 5];
const unique = uniqueArray(array); // [1, 2, 3, 4, 5]而使用Set,代碼可以簡(jiǎn)化為:

但代碼簡(jiǎn)潔只是表面優(yōu)勢(shì),真正的價(jià)值在于性能提升。
二、性能對(duì)比:數(shù)字以為自己聽(tīng)錯(cuò)了
讓我們通過(guò)幾種常見(jiàn)的去重方法進(jìn)行性能對(duì)比:
- Set方法
 - 傳統(tǒng)的indexOf方法
 - 使用對(duì)象(Object)作為哈希表
 - 使用Array.includes方法
 - 使用filter + indexOf
 
三、測(cè)試方法
我們將創(chuàng)建不同大小的數(shù)組進(jìn)行測(cè)試,每個(gè)數(shù)組包含隨機(jī)生成的數(shù)字,并確保約有30%的元素是重復(fù)的:

四、測(cè)試結(jié)果
以下是在不同大小數(shù)組上各方法的執(zhí)行時(shí)間(單位:毫秒):
方法  | 100元素  | 10,000元素  | 1,000,000元素  | 
Set  | 0.05  | 1.2  | 85  | 
Object哈希表  | 0.08  | 2.8  | 120  | 
indexOf  | 0.2  | 350  | 超過(guò)30秒  | 
includes  | 0.2  | 380  | 超過(guò)30秒  | 
filter+indexOf  | 0.3  | 800  | 超過(guò)60秒  | 
在百萬(wàn)級(jí)數(shù)據(jù)上,Set比傳統(tǒng)indexOf方法快了約300倍以上。
五、為什么Set如此高效?
Set之所以能提供如此驚人的性能優(yōu)勢(shì),主要有以下幾個(gè)原因:
1. 數(shù)據(jù)結(jié)構(gòu)的本質(zhì)區(qū)別
Set是基于哈希表實(shí)現(xiàn)的,這意味著:
- 查找、添加和刪除操作的時(shí)間復(fù)雜度為O(1)
 - 每個(gè)值在底層都有唯一的"地址",可以直接訪問(wèn)
 
而Array的indexOf和includes方法需要線性搜索,時(shí)間復(fù)雜度為O(n)。
2. 引擎優(yōu)化
JavaScript引擎對(duì)Set進(jìn)行了特殊優(yōu)化:
- V8引擎中,Set使用哈希表和紅黑樹(shù)的組合實(shí)現(xiàn)
 - Set在內(nèi)存中的布局更適合現(xiàn)代CPU的緩存機(jī)制
 - 引擎可以對(duì)Set操作應(yīng)用更多底層優(yōu)化
 
3. 自動(dòng)處理邊緣情況
Set能正確處理JavaScript中的特殊值:

注意Set正確地將NaN與NaN視為相同(盡管NaN !== NaN),并且區(qū)分了0和"0"。
六、什么時(shí)候不應(yīng)該使用Set?
盡管Set有許多優(yōu)勢(shì),但也不是所有場(chǎng)景都適合:
- 需要保持原始順序:雖然現(xiàn)代瀏覽器中Set是有序的(按插入順序),但這并不是規(guī)范保證的
 - 需要索引訪問(wèn):Set不支持索引訪問(wèn)(如set[0])
 - 需要頻繁修改:如果需要頻繁修改集合中的元素,數(shù)組的API可能更方便
 - 處理非原始類型:對(duì)于對(duì)象等非原始類型,Set使用引用相等,可能不符合預(yù)期
 
七、最佳實(shí)踐:Set和Array結(jié)合使用
現(xiàn)代前端開(kāi)發(fā)中,一個(gè)常見(jiàn)的模式是Set和Array結(jié)合使用:
// 數(shù)據(jù)處理流程
constprocessData = (dataArray) => {
// 1. 去重
const uniqueData = [...newSet(dataArray)];
// 2. 使用數(shù)組方法進(jìn)行處理
return uniqueData
    .filter(item => item > 10)
    .map(item => item * 2)
    .sort((a, b) => a - b);
};這種模式結(jié)合了Set的高效去重能力和Array豐富的數(shù)據(jù)處理方法。















 
 
 










 
 
 
 