title: ES6中的Symbol
-
函數前不能使用Symbol
指令,否則會報錯。這是因為生成的 Symbol 是一個原始類型的值,不是對象。也就是說,由于 Symbol 值不是對象,是以不能添加屬性。基本上,它是一種類似于字元串的資料類型。new
-
函數可以接受一個字元串作為參數,表示對 Symbol 執行個體的描述,主要是為了在控制台顯示,或者轉為字元串時,比較容易區分。Symbol
-
函數的參數隻是表示對目前 Symbol 值的描述,是以相同參數的Symbol
函數的傳回值是不相等的。Symbol
-
值不能與其他類型的值進行運算,會報錯。Symbol
-
值也可以轉為布爾值,但是不能轉為數值。Symbol
-
值一般用作屬性名,以防止某個鍵被覆寫或改寫。Symbol
-
let mySymbol = Symbol(); // 第一種寫法 let a = {}; a[mySymbol] = 'Hello!'; // 第二種寫法 let a = { [mySymbol]: 'Hello!' }; // 第三種寫法 let a = {}; Object.defineProperty(a, mySymbol, { value: 'Hello!' }); // 以上寫法都得到同樣結果 a[mySymbol] // "Hello!"
- 但是
值作為對象的屬性名時不能用點運算符:Symbol
const mySymbol = Symbol(); const a = {}; a.mySymbol = 'Hello!'; a[mySymbol] // undefined a['mySymbol'] // "Hello!"
-
- 在對象内部使用
值定義屬性時,Symbol
值必須放在方括号中Symbol
-
let s = Symbol(); let obj = { [s]: function (arg) { ... } // 或是對象增強寫法: [s](arg) { ... } }; obj[s](123);
-
一. 屬性名的周遊
作為屬性名的
Symbol
值和其他字元串類型的鍵不同,無法通過
for...in
、
for...of
循環中,也不會被
Object.keys()
、
Object.getOwnPropertyNames()
、
JSON.stringify()
傳回。
它通過
Object.getOwnPropertySymbols
方法傳回指定對象的所有
Symbol
屬性名(傳回一個數組)
故通過此方法可以為對象定義一些非私有的、但又希望隻用于内部的方法
let size = Symbol('size');
class Collection {
constructor() {
this[size] = 0;
}
add(item) {
this[this[size]] = item;
this[size]++;
}
static sizeOf(instance) {
return instance[size];
}
}
let x = new Collection();
Collection.sizeOf(x) // 0
x.add('foo');
Collection.sizeOf(x) // 1
Object.keys(x) // ['0']
Object.getOwnPropertyNames(x) // ['0']
Object.getOwnPropertySymbols(x) // [Symbol(size)]
另一個新的 API,
Reflect.ownKeys
方法可以傳回所有類型的鍵名,包括正常鍵名和 Symbol 鍵名。
二. 子產品的Singleton模式
Singleton
模式指的是調用一個類,任何時候傳回的都是同一個執行個體。
對于
node
來講,子產品檔案可以看作是一個類,為了保證每次執行此子產品檔案傳回的都是同一個執行個體,我們常把執行個體放到頂層對象
global
// mod.js
function A() {
this.foo = 'hello';
}
if (!global._foo) {
global._foo = new A();
}
module.exports = global._foo;
然後加載上邊的
mod.js
const a = require('./mod.js');
console.log(a.foo);
但問題是我們必須令引用
mod.js
的諸多檔案既可以使用,又無法修改
為防止此情況的發生,我們可以使用
Symbol
// mod.js
const FOO_KEY = Symbol('foo');
function A() {
this.foo = 'hello';
}
if (!global[FOO_KEY]) {
global[FOO_KEY] = new A();
}
module.exports = global[FOO_KEY];
若鍵名使用
Symbol
方法生成,那麼外部将無法引用這個值,自然也無法改寫。