es6-Symbol類型

在es5中有五種基本類型分別是字符串,數字,布爾,nullundefined,在es6中引入一種新的基本類型 Symbol,表示獨一無二的值。經常使用於模擬建立對象的私有屬性。html

基本用法

調用全局函數 Symbol 建立,該函數接收一個字符串做爲描述參數:es6

let sb = Symbol('sb');

console.log(sb); // Symbol(sb)
console.log(typeof sb); // symbol
複製代碼

不能使用 new 調用,由於 Symbol 是基本類型,不是返回對象。函數

由於 Symbol 自己表示獨一無二的值,因此兩個相同描述的 Symbol 是不相等的:post

let sb = Symbol('sb');
let sb2 = Symbol('sb');

console.log(sb === sb2); // false
複製代碼

對象做爲描述會先調用對象的 toString 方法:ui

let obj = {
  toString() {
    return 'Symbol obj';
  }
};

let sb = Symbol(obj);

console.log(sb); // Symbol(Symbol obj)
複製代碼

不能經過運算強制轉換爲字符串和數字:this

let sb = Symbol('sb');
let desc = sb + ''; // Cannot convert a Symbol value to a string
let num = sb + 1; // Cannot convert a Symbol value to a number
複製代碼

Symbol相關方法

有時候咱們須要用到同一個 Symbol 來作一些處理,就要用到 Symbol.for 方法來註冊一個全局的 Symboles5

let sb = Symbol.for('sb');
let sb2 = Symbol.for('sb');
let obj = {
  [sb]: '12345'
};

console.log(obj[sb]);  // 12345
console.log(sb === sb2); // true
console.log(obj[sb2]); // 12345
複製代碼

調用該方法會先在全局的Symbol註冊表中查找有沒有鍵爲'sb'的 Symbol,若是存在則返回。不存在就先建立一個新的 Symbol ,並在全局表中註冊。spa

Symbol.keyFor 方法返回在Symbol全局註冊表中檢索與該 Symbol 有關的key:prototype

let sb = Symbol.for('sb');

console.log(Symbol.keyFor(sb)); // sb

let sb2 = Symbol('sb');

console.log(Symbol.keyFor(sb2));  // undefined
複製代碼

Symbol 做爲對象的屬性沒法在 Object.keysObject.getOwnPropertyNames 方法返回,es6提供一個Object.getOwnPropertySymbols 方法來返回對象全部的 Symbol 屬性。code

let sb = Symbol('sb');
let obj = {
  [sb]: '12345'
};

let symbols = Object.getOwnPropertySymbols(obj);

console.log(symbols);   // [ Symbol(sb) ]
console.log(obj[symbols[0]]);  // 12345
複製代碼

well-know Symbol

es6提供了一些內置的 Symbol 變量,用於改變js中某些行爲。好比設置構造函數的Symbol.hasInstance 能夠自定義 instanceof 的行爲:

function SpecialNumber() {
  //
}

Object.defineProperty(SpecialNumber, Symbol.hasInstance, {
  value: function(v) {
    return v instanceof Number && (v >= 1 && v <= 100);
  }
});

let zero = new Number(0),
  two = new Number(2);

console.log(zero instanceof SpecialNumber); // false
console.log(two instanceof SpecialNumber); // true
複製代碼

Symbol.toStringTag 能夠改變調用 Object.prototype.toString 方法的默認行爲:

function Person(name) {
  this.name = name;
}

Person.prototype[Symbol.toStringTag] = 'Person';

Person.prototype.toString = function() {
  return this.name;
};

const person = new Person('wozien');

console.log(Object.prototype.toString.call(person)); // [object Person]
console.log(person.toString());  // wozien
複製代碼

其餘內置的Symbol及用法參考MDN文檔

應用場景

做爲對象的屬性和方法,模擬對象的私有化:

let myKey = Symbol();
let myFunc = Symbol();
let obj = {
  [myKey]: '123',
  [myFunc]() {
    return 'bar';
  }
};
console.log(obj[myKey]);  // 123
console.log(obj[myFunc]()); // bar
複製代碼

定義常量,防止常量重複定義:

const COLOR_RED = Symbol('red');
const COLOR_BLUR = Symbol('blue');
const COLOR_PINK = Symbol('pink');

switch (color) {
  case COLOR_RED:
    break;
  case COLOR_BLUR:
    break;
  //
}
複製代碼

** 做爲類型的私有屬性 ** 。防止定義的衝突和外部訪問:

const PASSWORD = Symbol();
class Login {
    constructor(name, password) {
        this.name = name;
        this[PASSWORD] = password;
    }
    hasPassword(pw) {
        return this[PASSWORD] === pw;
    }
}
複製代碼

** 自定義對象的迭代行爲 ** :

let obj = {
  data: ['hello', 'world'],
  [Symbol.iterator]() {
    const self = this;
    let index = 0;
    return {
      next() {
        if (index < self.data.length) {
          return {
            value: self.data[index++]
          };
        } else {
          return { done: true };
        }
      }
    };
  }
};

for (let x of obj) {
  console.log(x);
}

// hello
// world
複製代碼

參考

Symbol-MDN

symbol的用法和場景

>>>原文地址

相關文章
相關標籤/搜索