1. 程式人生 > 實用技巧 >一種新的資料型別Symbol

一種新的資料型別Symbol

symbol 是一種基本資料型別 (primitive data type)。Symbol()函式會返回symbol型別的值,該型別具有靜態屬性和靜態方法。它的靜態屬性會暴露幾個內建的成員物件;它的靜態方法會暴露全域性的symbol註冊,且類似於內建物件類,但作為建構函式來說它並不完整,因為它不支援語法:"new Symbol()"。每個從Symbol()返回的symbol值都是唯一的。一個symbol值能作為物件屬性的識別符號;這是該資料型別僅有的目的。

他是一個新的基本資料型別並且為唯一值

let s1 = Symbol()
let s2 = Symbol()
console.log(s1);
console.log(s1===s2); // false

symbol 會自動呼叫原型中的toString方法

const obj = {
  name: 'es6',
  toString () {
    return this.name
  }
}
let s = Symbol(obj)
console.log(s) // 輸出es6

API

Symbol.for() 會去尋找是否宣告過,如果已宣告將會指向同一個,否則註冊一個Symbol

let s1 = Symbol('foo')
let s2 = Symbol('foo')
console.log(s1===s2) // false

Symbol.keyFor() 返回一個已經註冊的 Symbol

const s1 = Symbol('foo')
console.log(Symbol.keyFor(s1));  // undefined

const s2 = Symbol.for('foo')
console.log(Symbol.keyFor(s2));  // foo

應用場景

  1. 當物件中需存入兩個鍵名相同的鍵值對時(例如姓名相同的人),可使用Symbol來區分.
const stu1 = Symbol('李四')
const stu2 = Symbol('李四')

const grade = {
   [stu1]: {
     address: 'xxx',
     tel:'1111'
   },
   [stu2]: {
     address: 'xxx',
     tel:'22222'
   }
 }
 
console.log(grade); // 並沒有被覆蓋掉
console.log(grade[stu2]); // {address: 'xxx',tel:'22222'}
  1. 可以對物件進行封裝, 類似於隱藏屬性, 通過for in遍歷不出, 通過let key of Reflect.ownKeys(obj) 可以遍歷出
const sym = Symbol('es5')
class User {
  constructor(name) {
    this.name = name
    this[sym] = 'es6'
  }
  getName () {
    return this.name + ' ' + this[sym]
  }
}
const user = new User('es5')
console.log(user.getName()); // es5 es6

for (let key in user) {
   console.log(key);
} // name

for (let key of Object.getOwnPropertySymbols(user)) {
  console.log(key);
} // name Symbol(es5)
  1. 消除魔術字串

魔術字串指的是,在程式碼之中多次出現、與程式碼形成強耦合的某一個具體的字串或者數值。風格良好的程式碼,應該儘量消除魔術字串,改由含義清晰的變數代替。

function getArea (shape) {
  let area = 0
  switch (shape) {
    case 'Triangle': 
      area = 1
      break
    case 'Circle': 
      area = 2
      break
  }
  return area
}

console.log(getArea('Triangle')); //1

使用Symbol()的唯一性代替原來'Triangle',程式碼看起來更加清晰,減少出錯率

const shapeType = {
  triangle: Symbol(),
  circle: Symbol()
}
function getArea (shape) {
  let area = 0
  switch (shape) {
    case shapeType.triangle: 
      area = 1
      break
    case shapeType.circle: 
      area = 2
      break
  }
  return area
}
console.log(getArea(shapeType.circle)); // 2