ES6 新特徵之Symbol

ES6 中除了 JavaScript 中幾種基本的數據類型,Number StringBooleanObjectnullundefined 之外,還新引入了一種新的原始數據類型 Symbol,表示獨一無二的值,屬於類字符串數據類型,能夠用來定義對象的惟一屬性名。函數

基本使用

ES5 的對象屬性名都是字符串,這容易形成屬性名的衝突。而 ES6 中新引入的 Symbol 類型能夠解決這個問題。Symbol 值是經過 Symbol 函數來生成的,能夠用來定義對象的惟一屬性名。屬於 Symbol 類型的屬性名,都是獨一無二的,能夠保證不會與其餘屬性名產生衝突。prototype

示例:
let sym = Symbol();
console.log(typeof sym);  // 輸出:symbol

上述代碼中,變量 sym 就是一個獨一無二的值。使用 typeof 運算符能夠知道,symSymbol 數據類型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

上述代碼中,sym1sym2 是兩個 Symbol 值,若是不加參數,則它們的輸出都爲Symbol(),不利於區分。ip

可是相同的參數 Symbol() 返回的值也是不相等的,咱們來看一下:字符串

let sym1 = Symbol('xkd');
let sym2 = Symbol('xkd');

console.log(sym1 === sym2); // 輸出:false

Symbol不能參與運算

Symbol 值不能與其餘類型的值進行運算,不然會報錯。get

示例:

例以下面代碼中使用字符串類型數據 helloSymbol 類型數據 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.prototype.description

在建立 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...infor...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.for() 方法是惟一一個能讓兩個 Symbol 相等的方法,尋找全局環境下某個描述下面的這個 Symbol,若是找到了那麼就返回這個 Symbol,不然就會生成一個新的 Symbol,也就是返回當前索引 Symbol

示例:
let symbol1 = Symbol.for('xkd');
let symbol2 = Symbol.for('xkd');
console.log(symbol1 === symbol2);
// 輸出:true

Symbol.keyFor()方法

Symbol.keyFor() 方法能夠返回已登記的 Symbolkey

示例:
let syb1 = Symbol.for("xkd");
console.log(Symbol.keyFor(syb1));
// 輸出: xkd

let syb2 = Symbol("xkd");
console.log(Symbol.keyFor(syb2));
// 輸出: undefined
相關文章
相關標籤/搜索