9.Symbol

概述

ES6 引入了一種新的原始數(shù)據(jù)類型 Symbol,表示獨一無二的值。Symbol 值通過 Symbol 函數(shù)生成;

ES6 之后的數(shù)據(jù)類型

undefined null Boolean String Number Object Symbol
是否引用類型

Symbol()

使用方法 返回值
Symbol(str) Symbol 類型的數(shù)據(jù)
let s1 = Symbol("foo");
let s2 = Symbol("bar");

s1; // Symbol(foo)
s2; // Symbol(bar)

s1.toString(); // "Symbol(foo)"
s2.toString(); // "Symbol(bar)"

自述

Symbol(str) 類似一個加密和隨機數(shù)生成的結(jié)合體,下面的例子簡單模擬它的工作原理

const Symbol = (str = "") => {
  return str + Math.random();
};

我們現(xiàn)在在用 redux 的時候經(jīng)常需要寫一堆的 action.type,如果我們用 Symbol 來生成的話可以省去很大的工作量,如下

// 最初始
dispatch({type:'action1',value:2})
dispatch({type:'action2',value:2})

// 傳統(tǒng)的
// config.js
export const actions = {
  action1 : 'action1'
  action2 : 'action2'
  ... // 幾十上百次重復(fù)勞動
}
// actions.js
import { actions } from './config.js'
const {action1, action2} = actions

dispatch({type:action1,value:2})
dispatch({type:action2,value:2})

// 新的
// config.js
const actions = {}
['action1','action2',...].forEach(key =>{ actions[key] = Symbol() });
export actions

// actions.js
import { actions } from './config.js'
const {action1, action2} = actions

dispatch({type:action1,value:2})
dispatch({type:action2,value:2})

通過對比上面三種使用方法我們會發(fā)現(xiàn),第一種最不容易維護,一旦我要改變某個 action.type 我需要去翻所有的頁面,第二種和第三者維護成本相當,但是因為我并不需要確切的知道 action.type 是什么,我只要知道我發(fā)出的 action 和我的處理函數(shù)能夠?qū)?yīng)就好了,所以很顯然,完成同樣功能的清空像第三種方式可以讓我節(jié)省接近一半的代碼量。

Symbol 帶來的問題

Symbol 作為屬性名,該屬性不會出現(xiàn)在 for...in、for...of 循環(huán)中,也不會被 Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()返回。

這樣會導(dǎo)致我們常用的 Object.keys() 出現(xiàn)問題,獲取不到全部的 key

// 這里拿不到Symbol類型 的key
Object.keys(obj).forEach(key => {})

那怎么辦呢?說了這么多,難道我們只能 Symbol 和 Object.keys()二選一? 當然不會了

另一個新的 API,Reflect.ownKeys 方法可以返回所有類型的鍵名,包括常規(guī)鍵名和 Symbol 鍵名。

let obj = {
  [Symbol("my_key")]: 1,
  enum: 2,
  nonEnum: 3
};

Reflect.ownKeys(obj);
//  ["enum", "nonEnum", Symbol(my_key)]

Symbol.for(),Symbol.keyFor()

有時,我們希望重新使用同一個 Symbol 值,Symbol.for 方法可以做到這一點。它接受一個字符串作為參數(shù),然后搜索有沒有以該參數(shù)作為名稱的 Symbol 值。如果有,就返回這個 Symbol 值,否則就新建并返回一個以該字符串為名稱的 Symbol 值。

let s1 = Symbol.for("foo");
let s2 = Symbol.for("foo");

s1 === s2; // true

我們可以用一段代碼來簡單模擬這個 api 做的事

windows.Memory = {},
const Symbol_ = {
  for(str) {
    if (!Memory[str]) {
      let s = Symbol(str);
      Memory[str] = s;
      return s;
    }
    return Memory[str];
  }
};
let a = Symbol_.for("go");
let b = Symbol_.for("go");
a === b; // true

ES6 內(nèi)置的11個 Symbol 值

name 說明
對象的Symbol.hasInstance屬性 當其他對象使用instanceof運算符,判斷是否為該對象的實例時,會調(diào)用這個方法。比如,foo instanceof Foo在語言內(nèi)部,實際調(diào)用的是Foo[Symbol.hasInstance](foo)。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本文為阮一峰大神的《ECMAScript 6 入門》的個人版提純! babel babel負責將JS高級語法轉(zhuǎn)義,...
    Devildi已被占用閱讀 2,129評論 0 4
  • 1.概述 ES5的對象屬性名都是字符串,這容易造成屬性名的沖突。比如,你使用了一個他人提供的對象,但又想為這個對象...
    趙然228閱讀 880評論 2 10
  • 概述 ES5 的對象屬性名都是字符串,這容易造成屬性名的沖突。比如,你使用了一個他人提供的對象,但又想為這個對象添...
    Masami_9e88閱讀 266評論 0 0
  • 概述 ES5的對象屬性名都是字符串,這容易造成屬性名的沖突。比如,你使用了一個他人提供的對象,但又想為這個對象添加...
    oWSQo閱讀 590評論 1 3
  • 沒有誰真正明白對方的心,縱使再相愛,也不能感同身受。人都是在經(jīng)過千瘡百孔中磨礪中成長的,都會有不被理解不愿告知的事...
    明明白白我得心閱讀 195評論 0 0

友情鏈接更多精彩內(nèi)容