ES6英華:Symbol

它是JS的第七種範例,屬於基礎範例。
它示意一個舉世無雙的值,行動相似字符串。
它是直接經由過程Symbol函數天生的,能夠傳入字符作為該值的形貌。

const symbol1 = Symbol('unique');
const symbol2 = Symbol('unique');
console.log(symbol1 === symbol2); // false

運用舉例

替換用於辨認的字符串常量

--- 之前
const MY_ONE = 'unique-one';
if (MY_ONE === 'unique-one') { ... }
雖然定義了保留值的常量,但直接運用值或再定義雷同值的變量也是沒有問題的。

--- 如今
const MY_ONE = Symbol('one');
if (MY_ONE === MY_ONE) { ... }
假如想運用該常量,必需直接運用該常量或其一個副本,由於 Symbol('one') 是相對唯一的。

作為間接完成私有屬性和要領的門路

只要運用 private_a / private_b 變量所指向的值才訪問到響應的屬性值。

const private_a = Symbol('private_a');
const private_b = Symbol('private_b');

function Class() {
  this[private_a] = 'private_a';
}

Class.prototype[private_b] = function() {
  console.log('private_b');
}

作為自定義接口或差別數據鳩合一致接口的稱號

示例:為 Array 增添並集的盤算要領,運用此要領能夠防止將來能夠的定名爭執。

const CusArrayAPIMap = {
  union: Symbol('cus-array-api-union')
};

Array[CusArrayAPIMap.union] = function() {
  return [...new Set([...arguments].reduce((a, b) => a.concat(b), []))];
};

Array[CusArrayAPIMap.union]([1, 3], [2, 3]); // [1, 3, 2]

轉化劃定規矩

symbol值不可轉化成数字(作為一個唯一值無對應的數值)。
symbol值能夠轉化成布爾值(不管怎樣,它是有值的,所以恆為true)。
symbol值不可被隱式轉化成字符串,然則能夠顯現轉化(隱式即盤算,拿一個唯一值盤算沒意義,但直接打印成字符串查看是能夠的)。

Symbol() + 2; // 報錯
Number(Symbol()); // 報錯

Boolean(Symbol()); // 恆為 true
if (Symbol()) { ... } // 恆實行

Symbol() + '-'; // 報錯
String(Symbol()); // "Symbol()"
Symbol().toString(); // "Symbol()"

Symbol.for()

Symbol.for(key)Symbol()一樣,用來返回一個唯一值。
不過其傳入的key與天生的值會構成映照存儲在全局的symbol註冊表中。
等於說,Symbol.for(key)是先依據key在註冊表中尋覓,有直接返回,沒有建立並返回。
也等於說,在雷同的全局空間中(包含差別的iframeservice worker)傳入雷同的key取出來的是統一值。

Symbol('one') === Symbol('one'); // false
Symbol('one') === Symbol.for('one'); // false
Symbol.for('one') === Symbol.for('one'); // true
Symbol.for('one') === Symbol.for('two'); // false

相配套的另有要領Symbol.keyFor()
它會依據傳入的Symbol值,去註冊表中查找並返回對應的key

let o = Symbol.for('one');

Symbol.keyFor(o); // 'one'
Symbol.keyFor(Symbol('two')); // undefined
Symbol.keyFor(Symbol.for('two')); // 'two'

內置的 Symbol 值

ES6劃定了11個內置接口的一致稱號。
能夠將這些接口布置到自定義對象或組織函數上,同步原生操縱。

Symbol.toStringTag
指向一個字符串,示意該對象的範例標籤。
淺顯的說,就是運用Object.prototype.toString.call(target)獲取到的[object Name]中的Name

let obj = {
  [Symbol.toStringTag]: 'MyTag'
};
console.log( Object.prototype.toString.call(target) ); // '[object MyTag]'

Symbol.toPrimitive
指向一個要領,當該對象被轉化成NumberString型時會被挪用。
該要領會接收一個字符串參數,示意當前場所須要轉化成什麼範例,一共有三種形式:numberstringdefault(轉化成二者都行)。

let obj = {
  [Symbol.toPrimitive](type) {
    switch(type) {
      case 'number':
        return 3;
        break;
      case 'string':
        return 's';
        break;
      case 'default':
        return 'd';
        break;
    }
  }
};

console.log( Number(obj) ); // 3
console.log( String(obj) ); // 's'
console.log( obj + 1 );  // 'd1'

Symbol.hasInstance
指向一個要領,是instanceof敕令現實挪用的要領。

[] instanceof Array; // true
現實是實行下面代碼。
Array[Symbol.hasInstance]([]); // true

可自行動自定義對象增加此接口。
let OBJ = {
  [Symbol.hasInstance](arr) {
    return arr.length === 2 ? true : false;
  }
};
[1] instanceof OBJ; // false
[1, 2] instanceof OBJ; // true

Symbol.iterator
指向對象的默許遍歷器要領(關於遍歷器可看Iterator章節)。
數組默許的遍歷器要領為:Array.prototype[Symbol.iterator]

Symbol.species
指向一個要領,該要領返回一個組織函數。當實例須要挪用本身的組織函數時要領會被挪用。
有些類庫是在基類的基礎上修正的,當子類運用繼續的要領時,作者願望返回基類的實例,而不是子類的實例。

class MyArray extends Array {
  static get [Symbol.species]() { return Array }
}

let a = new MyArray(1, 2, 3);
let b = a.map(x => x);
console.log(b instanceof Array); // true
console.log(b instanceof MyArray); // false

b 是 a 的衍生對象,或稱派生對象。
假如沒有 [Symbol.species] ,b 原型鏈中第一個對象應為 MyArray 原型。
但如今第一個對象為 Array 的原型,即 b 直接為 Array 的實例。

Symbol.split, Symbol.match, Symbol.search, Symbol.replace
四者都是針對字符串與正則(對象)的關聯,指向一個要領,具有雷同行動。

let reg = /m/g;
let str = 'Hi, I\'m programmer monkey';

str.replace(reg, 'M');
現實是實行下面的代碼。
reg[Symbol.replace](str, 'M');

Symbol.isConcatSpreadable
指向一個布爾值,示意該對象用於Array.prototype.concat()時是不是能夠睜開。
默許沒有該屬性,即為undefined,等同於true。設置為false則不睜開。

let arr = [1, 2];
arr[Symbol.isConcatSpreadable] = false;
[3].concat(arr); // [3, [1, 2]]

Symbol.unscopables
指向一個對象,該對象指定了運用with關鍵字時,哪些屬性會被with環境消除。

let obj = {
  id: '123',
  name: 'limo',
  [Symbol.unscopables]: {
    id: true
  }
};

let id = 'id';
let name = 'name';

with (obj) {
  console.log(id); // 'id'
  console.log(name); // 'limo'
}
    原文作者:wmaker
    原文地址: https://segmentfault.com/a/1190000015244917
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞