它是JS
的第七種類型,屬於基本類型。
它表示一個獨一無二的值,行爲相似字符串。
它是直接經過Symbol
函數生成的,能夠傳入字符做爲該值的描述。api
const symbol1 = Symbol('unique'); const symbol2 = Symbol('unique'); console.log(symbol1 === symbol2); // false
替代用於識別的字符串常量數組
--- 以前 const MY_ONE = 'unique-one'; if (MY_ONE === 'unique-one') { ... } 雖然定義了保存值的常量,但直接使用值或再定義相同值的變量也是沒有問題的。 --- 如今 const MY_ONE = Symbol('one'); if (MY_ONE === MY_ONE) { ... } 若是想使用該常量,必須直接使用該常量或其一個副本,由於 Symbol('one') 是絕對惟一的。
做爲間接實現私有屬性和方法的途徑函數
只有使用 private_a / private_b 變量所指向的值才能訪問到相應的屬性值。 const private_a = Symbol('private_a'); const private_b = Symbol('private_b'); function Class() { this[private_a] = 'private_a'; } Class.prototype[private_b] = function() { console.log('private_b'); }
做爲自定義接口或不一樣數據集合統一接口的名稱this
示例:爲 Array 增長並集的計算方法,使用此方法能夠避免將來可能的命名衝突。 const CusArrayAPIMap = { union: Symbol('cus-array-api-union') }; Array[CusArrayAPIMap.union] = function() { return [...new Set([...arguments].reduce((a, b) => a.concat(b), []))]; }; Array[CusArrayAPIMap.union]([1, 3], [2, 3]); // [1, 3, 2]
symbol
值不可轉化成數字(做爲一個惟一值無對應的數值)。 symbol
值能夠轉化成布爾值(無論怎樣,它是有值的,因此恆爲true
)。 symbol
值不可被隱式轉化成字符串,可是能夠顯示轉化(隱式即計算,拿一個惟一值計算沒意義,但直接打印成字符串查看是能夠的)。prototype
Symbol() + 2; // 報錯 Number(Symbol()); // 報錯 Boolean(Symbol()); // 恆爲 true if (Symbol()) { ... } // 恆執行 Symbol() + '-'; // 報錯 String(Symbol()); // "Symbol()" Symbol().toString(); // "Symbol()"
Symbol.for(key)
與Symbol()
同樣,用來返回一個惟一值。
不過其傳入的key
與生成的值會造成映射存儲在全局的symbol
註冊表中。
便是說,Symbol.for(key)
是先根據key
在註冊表中尋找,有直接返回,沒有建立並返回。
也便是說,在相同的全局空間中(包括不一樣的iframe
或service worker
)傳入相同的key
取出來的是同一值。code
Symbol('one') === Symbol('one'); // false Symbol('one') === Symbol.for('one'); // false Symbol.for('one') === Symbol.for('one'); // true Symbol.for('one') === Symbol.for('two'); // false
相配套的還有方法Symbol.keyFor()
。
它會根據傳入的Symbol
值,去註冊表中查找並返回對應的key
。對象
let o = Symbol.for('one'); Symbol.keyFor(o); // 'one' Symbol.keyFor(Symbol('two')); // undefined Symbol.keyFor(Symbol.for('two')); // 'two'
ES6
規定了11個內置接口的統一名稱。
能夠將這些接口部署到自定義對象或構造函數上,同步原生操做。繼承
Symbol.toStringTag
指向一個字符串,表示該對象的類型標籤。
通俗的說,就是使用Object.prototype.toString.call(target)
獲取到的[object Name]
中的Name
。接口
let obj = { [Symbol.toStringTag]: 'MyTag' }; console.log( Object.prototype.toString.call(target) ); // '[object MyTag]'
Symbol.toPrimitive
指向一個方法,當該對象被轉化成Number
或String
型時會被調用。
該方法會接受一個字符串參數,表示當前場合須要轉化成什麼類型,一共有三種模式:number
,string
和default
(轉化成二者都行)。ci
let obj = { [Symbol.toPrimitive](type) { switch(type) { case 'number': return 3; break; case 'string': return 's'; break; case 'default': return 'd'; break; } } }; console.log( Number(obj) ); // 3 console.log( String(obj) ); // 's' console.log( obj + 1 ); // 'd1'
Symbol.hasInstance
指向一個方法,是instanceof
命令實際調用的方法。
[] instanceof Array; // true 實際是執行下面代碼。 Array[Symbol.hasInstance]([]); // true 可自行爲自定義對象添加此接口。 let OBJ = { [Symbol.hasInstance](arr) { return arr.length === 2 ? true : false; } }; [1] instanceof OBJ; // false [1, 2] instanceof OBJ; // true
Symbol.iterator
指向對象的默認遍歷器方法(關於遍歷器可看Iterator
章節)。
數組默認的遍歷器方法爲:Array.prototype[Symbol.iterator]
。
Symbol.species
指向一個方法,該方法返回一個構造函數。當實例須要調用自身的構造函數時方法會被調用。
有些類庫是在基類的基礎上修改的,當子類使用繼承的方法時,做者但願返回基類的實例,而不是子類的實例。
class MyArray extends Array { static get [Symbol.species]() { return Array } } let a = new MyArray(1, 2, 3); let b = a.map(x => x); console.log(b instanceof Array); // true console.log(b instanceof MyArray); // false b 是 a 的衍生對象,或稱派生對象。 若是沒有 [Symbol.species] ,b 原型鏈中第一個對象應爲 MyArray 原型。 但如今第一個對象爲 Array 的原型,即 b 直接爲 Array 的實例。
Symbol.split, Symbol.match, Symbol.search, Symbol.replace
四者都是針對字符串與正則(對象)的關係,指向一個方法,具備相同行爲。
let reg = /m/g; let str = 'Hi, I\'m programmer monkey'; str.replace(reg, 'M'); 實際是執行下面的代碼。 reg[Symbol.replace](str, 'M');
Symbol.isConcatSpreadable
指向一個布爾值,表示該對象用於Array.prototype.concat()
時是否能夠展開。
默認沒有該屬性,即爲undefined
,等同於true
。設置爲false
則不展開。
let arr = [1, 2]; arr[Symbol.isConcatSpreadable] = false; [3].concat(arr); // [3, [1, 2]]
Symbol.unscopables
指向一個對象,該對象指定了使用with
關鍵字時,哪些屬性會被with
環境排除。
let obj = { id: '123', name: 'limo', [Symbol.unscopables]: { id: true } }; let id = 'id'; let name = 'name'; with (obj) { console.log(id); // 'id' console.log(name); // 'limo' }