它是JS
的第七種範例,屬於基礎範例。
它示意一個舉世無雙的值,行動相似字符串。
它是直接經由過程Symbol
函數天生的,能夠傳入字符作為該值的形貌。
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');
}
作為自定義接口或差別數據鳩合一致接口的稱號
示例:為 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
值不可被隱式轉化成字符串,然則能夠顯現轉化(隱式即盤算,拿一個唯一值盤算沒意義,但直接打印成字符串查看是能夠的)。
Symbol() + 2; // 報錯
Number(Symbol()); // 報錯
Boolean(Symbol()); // 恆為 true
if (Symbol()) { ... } // 恆實行
Symbol() + '-'; // 報錯
String(Symbol()); // "Symbol()"
Symbol().toString(); // "Symbol()"
Symbol.for()
Symbol.for(key)
與Symbol()
一樣,用來返回一個唯一值。
不過其傳入的key
與天生的值會構成映照存儲在全局的symbol
註冊表中。
等於說,Symbol.for(key)
是先依據key
在註冊表中尋覓,有直接返回,沒有建立並返回。
也等於說,在雷同的全局空間中(包含差別的iframe
或service worker
)傳入雷同的key
取出來的是統一值。
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'
內置的 Symbol 值
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
(轉化成二者都行)。
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'
}