symbol 是為解決對象屬性名沖突而引入的原始數據類型,每個 symbol 值都是唯一的。1. 創建方式是調用 symbol() 函數,如 const id = symbol(“id”);2. 常見用途包括作為對象的唯一鍵名、避免命名沖突、使用知名 symbol 實現語言特性,例如 symbol.iterator 支持迭代;3. 注意事項有 symbol 不參與 JSon 序列化、不會被 Object.assign() 復制,需用 symbol.for() 共享 symbol。
Symbol 是 JavaScript 中的一種原始數據類型,用來創建唯一的標識符。它在 es6(ecmascript 2015)中被引入,主要是為了解決對象屬性名沖突的問題。簡單來說,每個 Symbol 值都是獨一無二的,不會和其他任何值相等,即使它們的描述完全一樣。
為什么用 Symbol?
在 Symbol 出現之前,對象的屬性名只能是字符串。如果你在一個對象上添加了一個屬性,而這個屬性名剛好和別人寫的代碼中的屬性名重復了,就可能引發意想不到的問題。比如:
const user = { name: "Alice" }; // 其他人可能會不小心覆蓋掉你定義的屬性 user.name = "Bob";
雖然這只是一個簡單的例子,但在大型項目或庫中,這種情況更容易發生。Symbol 提供了一種方式來創建“私有”屬性,避免命名沖突。
怎么創建一個 Symbol?
創建 Symbol 非常簡單,使用 Symbol() 函數即可:
const id = Symbol("id");
這里的 “id” 是對這個 Symbol 的描述,主要用于調試時識別,不影響它的唯一性。
需要注意的是:
- 每次調用 Symbol() 都會生成一個新的、唯一的值。
- 不要使用 new 來創建 Symbol,否則會報錯。
Symbol 的常見用途
1. 作為對象的唯一鍵名
這是 Symbol 最常見的用法之一:
const user = {}; const id = Symbol("id"); user[id] = "12345"; console.log(user[id]); // 輸出 12345
這樣做的好處是:這個屬性不會被枚舉到,也不會出現在 Object.keys() 或 for…in 循環中。
2. 避免命名沖突
多個模塊或庫之間共享一個對象時,使用 Symbol 可以避免屬性名沖突。例如:
const myLib = { [Symbol("version")]: "1.0.0" };
其他庫就算也用了 “version” 這個名字,也不會沖突。
3. 使用知名 Symbol 實現語言特性
JavaScript 內置了一些知名的 Symbol,用于定義一些特殊行為,比如:
- Symbol.iterator:讓對象可以被迭代(如用 for…of 遍歷)
- Symbol.toPrimitive:控制對象轉原始值的行為
- Symbol.toStringTag:自定義對象的 toString() 返回值
例如,你可以自定義一個可迭代的對象:
const myIterable = { [Symbol.iterator]() { let step = 0; return { next() { step++; return { value: step, done: step > 3 } } }; } }; for (let val of myIterable) { console.log(val); // 輸出 1, 2, 3 }
注意事項
- Symbol 類型不能參與 json 序列化,也就是說用 JSON.stringify() 會忽略 Symbol 屬性。
- 如果你想全局共享某個 Symbol,可以用 Symbol.for(key) 和 Symbol.keyFor(sym)。
- Symbol 不會被 Object.assign() 或擴展運算符自動復制。
基本上就這些了。Symbol 雖然看起來不復雜,但在實際開發中特別適合用來做“隱藏”的標識符或者防止屬性沖突,用起來也很靈活。