深刻淺出ES6的Symbol類型

本文內容

  • JS基本數據類型種類
  • Symbol的主要用法, 全局Symbol的使用與檢測
  • Symbol與其餘基本類型轉換時的規則

ES6引入了一種新的原始數據類型,表示獨一無二的值,最大的用處是做爲對象屬性的惟一標識符。瀏覽器

至此,Javascript擁有6種基本數據類型和一種複雜數據類型。spa

數據類型

基本類型調試

  • string
  • number
  • boolean
  • undefined
  • null
  • symbol

複雜類型code

  • object

用法

基本語法

Symbol([description])
  • description 可選的描述,通常用在調試的時候做爲區分,可是 不能用來訪問Symbol
  • 該方法返回一個symbol值
let s = Symbol('test');
let s2 = Symbol('test');
let s3 = new Symbol('test'); // TypeError

console.log(s === s2); // false
console.log(typeof s); // symbol
console.log(s.description); // test
  • 每次調用Symbol()返回的值都是獨一無二的,無論描述是否一致。
  • Symbol不支持new調用
  • 經過description屬性能夠獲取到傳入Symbol的描述性字符串

全局單例的Symbol

使用Symbol.for()能夠建立全局單例的symbol值,語法以下:對象

Symbol.for([name])
  • name 可選的描述,建議傳入,不然name會做爲undefined傳入
  1. 相似於單例模式,執行環境(通常是瀏覽器)內部維護了一個全局Symbol註冊表,記錄name和Symbol(name)關係
  2. 嘗試經過name在該註冊表查找對應symbol值,若是找到,則返回這個symbol值
  3. 若是沒找到,則使用Symbol(name)建立一個symbol值,並記錄該symbol值與name的關聯關係,以後返回該symbol
const name = Symbol('name');
const name2 = Symbol.for('name');
const name3 = Symbol.for('name');

console.log(name === name2); // false
console.log(name2 === name3); // true
  • 全局Symbol映射關係中name是做爲字符串來使用的,結構相似下面的代碼:ip

    const globalSymbols = {
      name: Symbol('name')
    };
  • 使用一樣的字符串描述調用Symbol()和Symbol.for()獲取到的symbol值不相等

查找是否爲全局的單例Symbol

使用Symbol.keyFor()能夠檢測給定的symbol值是不是全局單例的symbol(簡單來講就是檢測是不是Symbol.for()建立的),語法以下:字符串

Symbol.keyFor(symbol)
  • symbol 必傳, 待檢測的symbol值
  • 若是給定的symbol值是經過Symbol.for()獲得的,該方法返回傳入symbol的字符串描述
  • 若是給定的symbol值不是經過Symbol.for()獲得的,該方法返回undefined
const s = Symbol('s1');
const s2 = Symbol.for('s2');

console.log(Symbol.keyFor(s)); // undefined
console.log(Symbol.keyFor(s2)); // s2

Symbol與JSON.stringify

Symbol類型的屬性不會參與JSON的序列化
const name = Symbol('name');
const obj = {
  [name]: 'xialei',
  data: 1
};
console.log(JSON.stringify(obj)); // {"data": 1}

Symbol與for ... in和for ... of

Symbol類型的屬性不會出如今for ... in和for ... of循環中
const name = Symbol('name');
const user = {
  [name]: 'xialei',
  data: 1
};

for(let i in user) {
  console.log(i, user[i]);
}
// 上述循環輸出 data 1

for(let i of user) {
  console.log(i, user[i]);
}
// TypeError: user不是可迭代對象

Symbol與Object.keys()和Object.getOwnPropertyNames()

Symbol類型的屬性不會出如今Object.keys()和Object.getOwnPropertyNames()返回結果中
const name = Symbol('name');
const user = {
  [name]: 'xialei',
  data: 1
};
console.log(Object.keys(user)); // ["data"]
console.log(Object.getOwnPropertyNames(user)); // ["data"]

Symbol與Object.getOwnPropertySymbols()

Symbol類型的屬性會出如今Object.Object.getOwnPropertySymbols()
const name = Symbol('name');
const user = {
  [name]: 'xialei',
  data: 1
};
console.log(Object.Object.getOwnPropertySymbols(user)); // [Symbol(name)]

Symbol數據類型轉換

const name = Symbol('1');
console.log(name + 1); // TypeError
console.log(Number(name)); // 建立包裝對象

console.log(name + '1'); // TypeError
console.log(String(name)); // Symbol(1)

console.log(!!name); // true
console.log(Boolean(name)); // true
  • symbol值不能轉換爲數字
  • symbol不能直接轉換爲字符串,須要經過String包裝才能轉化
  • symbol能夠直接轉換爲boolean,轉化後爲true

結尾

  • 使用Symbol最大的注意事項應該是使用方括號語法去訪問對應的屬性,而不是字符串。
  • Symbol數據類型轉換規範比較簡單,大部分場景下也沒用拿Symbol去作數據轉換

2019-10-22-102654.jpg

相關文章
相關標籤/搜索