ES6
中除了 JavaScript 中幾種基本的數據類型,Number
、String
、Boolean
、Object
、null
、undefined
之外,還新引入了一種新的原始數據類型 Symbol
,表示獨一無二的值,屬於類字符串數據類型,能夠用來定義對象的惟一屬性名。函數
ES5
的對象屬性名都是字符串,這容易形成屬性名的衝突。而 ES6
中新引入的 Symbol
類型能夠解決這個問題。Symbol
值是經過 Symbol
函數來生成的,能夠用來定義對象的惟一屬性名。屬於 Symbol
類型的屬性名,都是獨一無二的,能夠保證不會與其餘屬性名產生衝突。prototype
let sym = Symbol(); console.log(typeof sym); // 輸出:symbol
上述代碼中,變量 sym
就是一個獨一無二的值。使用 typeof
運算符能夠知道,sym
是 Symbol
數據類型code
須要注意的是,Symbol
函數前不能使用 new
命令,不然會報錯。由於 Symbol
是原始數據類型,不是對象。對象
Symbol
函數能夠接受一個字符串做爲參數,爲新建立的 Symbol
提供描述,用來顯示在控制檯或者做爲字符串的時候使用,便於區分。索引
let sym1 = Symbol(11); let sym2 = Symbol('xkd'); console.log(sym1); // 輸出:Symbol(11) console.log(sym2); // 輸出:Symbol(xkd) console.log(sym1 === sym2); // 輸出:false
上述代碼中,sym1
和 sym2
是兩個 Symbol
值,若是不加參數,則它們的輸出都爲Symbol()
,不利於區分。ip
可是相同的參數 Symbol()
返回的值也是不相等的,咱們來看一下:字符串
let sym1 = Symbol('xkd'); let sym2 = Symbol('xkd'); console.log(sym1 === sym2); // 輸出:false
Symbol
值不能與其餘類型的值進行運算,不然會報錯。get
例以下面代碼中使用字符串類型數據 hello
與 Symbol
類型數據 sym
相加,會報錯:string
let sym = Symbol('xkd'); console.log('hello' + sym); // 報錯信息:TypeError: Cannot convert a Symbol value to a string
Symbol
類型的值能夠轉換爲字符串或者布爾類型的值。io
將 Symbol
值顯示轉換爲字符串:
let sym = Symbol('xkd'); console.log(typeof String(sym)); // 輸出:string console.log(typeof sym.toString()); // 輸出:string
將 Symbol
值顯示轉換爲布爾值:
let symbol = Symbol(); console.log(typeof Boolean(symbol)); // 輸出: boolean
在建立 Symbol
時能夠添加一個描述,咱們經過 description
屬性能夠獲取描述內容。這個屬性是 ES2019
中新增的實例屬性。
例以下面代碼中,'你好,俠課島!'就是 sym
的描述:
const sym = Symbol('你好,俠課島!'); console.log(sym.description); // 輸出: 你好,俠課島!
Symbol
能夠做爲標識符,用於對象的屬性名,這樣能夠確保對象中不會出現同名的屬性。
let sym = Symbol(); let obj = {}; obj[sym] = 'xkd'; console.log(obj); // 輸出:{ [Symbol()]: 'xkd' }
上述代碼其實還有兩種寫法,第一種寫法爲:
let sym = Symbol(); let obj = { [sym]: 'xkd' }; console.log(obj); // 輸出:{ [Symbol()]: 'xkd' }
第二種寫法爲:
let sym = Symbol(); let obj = {}; Object.defineProperty(obj, sym, {value: 'xkd'}); console.log(obj); // 輸出:{ [Symbol()]: 'xkd' }
以上三種寫法都能獲得同樣的結果。
當 Symbol
值做爲對象屬性名時,不能用點運算符。
const sym = Symbol(); const obj = {}; obj.sym = 'xkd'; console.log(obj[sym]); // 輸出:undefined console.log(obj['sym']); // 輸出:xkd
在遍歷對象時,Symbol
做爲屬性名不會出如今 for...in
、for...of
循環中,也不會被 Object.keys()
、Object.getOwnPropertyNames()
、JSON.stringify()
返回。它們會把 Symbol
過濾掉,可是咱們能夠有兩種方法能夠獲取全部的 Symbol
屬性名。
Object.getOwnPropertySymbols
方法:const obj = {}; let sym1 = Symbol('111'); let sym2 = Symbol('222'); obj[sym1] = '111'; obj[sym2] = '222'; console.log(Object.getOwnPropertySymbols(obj)); // 輸出: [ Symbol(111), Symbol(222) ]
Reflect.ownKeys
方法:const obj = {}; let sym1 = Symbol('111'); let sym2 = Symbol('222'); obj[sym1] = '111'; obj[sym2] = '222'; console.log(Reflect.ownKeys(obj)); // 輸出: [ Symbol(111), Symbol(222) ]
Symbol.for()
方法是惟一一個能讓兩個 Symbol
相等的方法,尋找全局環境下某個描述下面的這個 Symbol
,若是找到了那麼就返回這個 Symbol
,不然就會生成一個新的 Symbol
,也就是返回當前索引 Symbol
。
let symbol1 = Symbol.for('xkd'); let symbol2 = Symbol.for('xkd'); console.log(symbol1 === symbol2); // 輸出:true
Symbol.keyFor()
方法能夠返回已登記的 Symbol
的 key
。
let syb1 = Symbol.for("xkd"); console.log(Symbol.keyFor(syb1)); // 輸出: xkd let syb2 = Symbol("xkd"); console.log(Symbol.keyFor(syb2)); // 輸出: undefined