開發者使用物件鍵值去重數字陣列 [2,1,2,10,2,3,4,1,85,321,3,4,65,10,24],但發現回傳結果型別與原陣列不一致(原為 number,去重後可能變為 string),詢問如何正確轉換。
原代碼中 keys(obj) 函數遍歷物件屬性時,for...in 取得的鍵值為 字串。雖然使用 parseInt(attr) 轉換,但若物件鍵值包含非數字屬性(如原型鏈汙染),或轉換邏輯有誤,會導致結果異常。此外,toObject 以數值作為鍵時,JavaScript 會自動轉為字串,若後續處理不當即會型別錯位。
Set + 擴展運算子(最簡潔、效能佳)const arr = [2,1,2,10,2,3,4,1,85,321,3,4,65,10,24];
const uniqueArr = [...new Set(arr)];
console.log(uniqueArr); // [2, 1, 10, 3, 4, 85, 321, 65, 24] 型別保持 number
Set 自動去重並保持插入順序,擴展運算子還原為陣列,完整保留原始型別。
Array.from(new Set(arr))const uniqueArr = Array.from(new Set(arr));
filter + indexOf(相容舊環境)const uniqueArr = arr.filter((value, index, self) => self.indexOf(value) === index);
此法對大陣列效能較差(O(n²)),但不需 ES6 支援。
若陣列元素為物件,Set 只能去除相同引用。需自訂比較邏輯:
// 依特定欄位去重
const uniqueBy = (arr, key) => [...new Map(arr.map(item => [item[key], item])).values()];
// 深度比較(效能較低)
const deepUnique = arr => arr.filter((item, i, self) =>
i === self.findIndex(t => JSON.stringify(t) === JSON.stringify(item))
);
function uniq(arr) {
const seen = {};
const result = [];
for (const val of arr) {
const key = typeof val + ':' + val; // 型別+值作鍵,區分 1 和 "1"
if (!seen[key]) {
seen[key] = true;
result.push(val);
}
}
return result;
}
[...new Set(arr)],簡潔、高效、保持型別與順序。filter + indexOf 或 Map 輔助。parseInt 物件鍵值,易出錯且效能低。