Symbol:表示獨一無二的值,屬於類字符串數據類型,本質上能夠當字符串來用。數組
// 1 let symbol = Symbol(); typeof symbol // symbol // 2 Symbol使用時不能使用new,它是一個函數,能夠接收參數,僅做爲描述 let symbol1 = Symbol('week'); symbol1; // Symbol(week) symbol1.toString(); // "Symbol(week)" // 3 let symbol1 = Symbol(); let symbol2 = Symbol(); symbol1 === symbol2; // false let symbol1 = Symbol('object'); let symbol2 = Symbol('object'); symbol1 === symbol2; // false // 4 隱式轉換 const obj = { toString() { return 'object'; } }; const symbol = Symbol(obj); symbol; // Symbol(object) // 5 不能參與運算 let symbol = Symbol('symbol'); "hello" + symbol; // TypeError: Cannot convert a Symbol value to a string // 6 類型轉換 String(symbol); symbol.toString(); // Symbol(symbol) let symbol = Symbol(); Boolean(symbol); // true Number(symbol); // TypeError: Cannot convert a Symbol value to a number
description
,Symbol的描述 const symbol = Symbol('symbollobmys'); symbol.description; // "symbol"
symbol應用場景
,對象屬性名 let symbol = Symbol(); let a = {}; a[symbol] = 'Hello!'; let a = { [symbol]: 'Hello!' }; let a = {}; Object.defineProperty( a, symbol, { value: 'Hello!' } );
屬性遍歷
屬性遍歷中的for...in、for...of、Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()都不會返回Symbol,它們會把Symbol過濾掉。可是咱們能夠有兩種方法獲得Symbol,一種是Object.getOwnPropertySymbols,另外一種是Reflect.ownKeys。 const obj = {}; let symbol1 = Symbol('symbol1'); let symbol2 = Symbol('symbol2'); obj[symbol1] = 'symbol1'; obj[symbol2] = 'symbol1'; Object.getOwnPropertySymbols(obj); // [Symbol(symbol1), Symbol(symbol2)] Reflect.ownKeys(obj); // [Symbol(symbol1), Symbol(symbol2)] // 能夠做爲非私有的內部方法
Symbol.for
(是惟一一個能讓兩個Symbol相等的),尋找全局的環境下某個描述下面的這個Symbol,若是找到某一個描述下的Symbol,那麼就會返回這個Symbol,若是沒有找到就會生成一個新的Symbol。簡而言之就是,返回當前索引Symbol。 let symbol1 = Symbol.for('week'); let symbol2 = Symbol.for('week'); symbol1 === symbol2; // true
Symbol.keyFor
,返回已登記的Symbol的key let symbol1 = Symbol.for("symbol1"); Symbol.keyFor(symbol1); // symbol1 let symbol2 = Symbol("week"); Symbol.keyFor(symbol2); // undefined
Symbol.hasInstance
,instanceof運算符調用 class MyClass { [Symbol.hasInstance](obj) { return obj instanceof Array; } } [1, 2, 3] instanceof new MyClass(); // true
Symbol.isConcatSpreadable
,控制數組concat是否展開 let array1 = [1, 2]; [3, 4].concat(array1, 5); // ['a', 'b', 'c', 'd', 'e'] array1[Symbol.isConcatSpreadable]; // undefined let array2 = [1, 2]; array2[Symbol.isConcatSpreadable] = false; [3, 4].concat(array2, 5); // [3, 4, [1, 2], 5]
Symbol.species
,爲衍生類指定原型 class MyArray extends Array { } const one = new MyArray(1, 2, 3); const two = a.map(x => x); const three = a.filter(x => x = 1); b instanceof MyArray; // true c instanceof MyArray; // true class MyArray extends Array { static get [Symbol.species]() { return Array; } } const one = new MyArray(1, 2, 3); const two = a.map(x => x); const three = a.filter(x => x = 1); b instanceof MyArray; // false c instanceof Array; // true
Symbol.match
,str.match調用 class Mather { [Symbol.match](string) { return 'hello world'; } } 'e'.match(new Mather()); // 'hello world'
Symbol.replace
,replace調用 const demo = {}; demo[Symbol.replace] = () => 'hello word'; 'Hello'.replace(demo, 'World'); // hello word
Symbol.search
Symbol.split
Symbol.iterator
,默認遍歷器 const diyIterable = {}; diyIterable[Symbol.iterator] = function* () { yield 'hello'; yield 'word'; }; [...diyIterable]; // ['hello', 'word']
Symbol.toPrimitive
,類型轉換調用 let object = { [Symbol.toPrimitive](hint) { switch (hint) { case 'number': return 1; case 'string': return 'hello'; case 'default': return 'word'; default: throw new Error('Cannot convert'); } } }; 2 * object; // 2 3 + object; // '3word' object == 'word'; // true String(object); // hello
Symbol.toStringTag
, 指定[object Object]或[object Array]中object後面字符串 ({ [Symbol.toStringTag]: 'Hello' }.toString()) // "[object Hello]"
Symbol.unscopables
, 指定被with排除的屬性,with是一個語句,它能夠擴展一個做用域鏈 // with語句 擴展一個語句的做用域鏈 var a, x, y; var r = 10; with (Math) { a = PI * r * r; x = r * cos(PI); y = r * sin(PI / 2); } class MyClass { week() { return 1; } get [Symbol.unscopables]() { return { week: true }; } } var week = function () { return 2; }; with (MyClass.prototype) { week(); // 2 }