在js中,Symbol是一種基本數據類型,是在ECMAScript 6 (ES6) 中引入的新特性。表示獨一無二
Symbol的定義
Symbol是不完整的構造函數,創建symbol對象時不需要new操作符,原因是通過 new 實例化的結果是一個 object 對象,而不是原始類型的 symbol。
var s = Symbol()
typeof s // 'symbol'
Symbol 方法接收一個參數,表示對生成的 symbol 值的一種描述。
var a = Symbol('a')
var b = Symbol('b')
a==b //false
即使是傳入相同的參數,生成的 symbol 值也是不相等的,因為 Symbol 本來就是獨一無二的意思。
Symbol的應用
- 作為對象的屬性
可以作為對象的屬性來解決屬性覆蓋問題,避免引發不必要的代碼沖突
var a = Symbol('a')let obj = {}obj[a] = 'test'obj // {Symbol(a): 'test'}
值得注意的是我們無法使用".“來調用對象的Symbol屬性,所以必須使用”[]"來訪問Symbol屬性
- 降低代碼耦合
當代碼中充斥著大量的魔法字符時,縱使是原開發者在經過一段時間后再回頭看也會變得難以理解,更不必說是交由后來開發者維護。
假如現有一個 Tabs 切換的功能:
if (type === 'basic') {return <div>basic tab</div>
}if (type === 'super') {return <div>super tab</div>
}
上面代碼中字符串 basic、super 就是與業務代碼無關的魔法字符,接下來使用 Symbol 對這塊代碼進行改造。
const tabTypes = {basic: Symbol(),super: Symbol(),
}if (type === tabTypes.basic) {return <div>basic tab</div>
}if (type === tabTypes.super) {return <div>super tab</div>
}
全局共享Symbol
如果我們想創建一個可供全局使用的symbol,那么我們需要用Symbol.for(),可以傳遞一個參數作為描述,該方法可以遍歷全局注冊表中的的Symbol,當搜索到相同描述,那么會調用這個Symbol,如果沒有搜索到,就會創建一個新的Symbol。
const a = Symbol.for('a')
const b = Symbol.for('a')
a === b // true
過程解析
1、首先通過Symbol.for()在全局注冊表中尋找描述為a的Symbol,而目前沒有符合條件的Symbol,所以創建了一個描述為a的Symbol
2、當聲明b并使用Symbol.for()在全局注冊表中尋找描述為a的Symbol,找到并賦值
3、比較a與b結果為true反映了Symbol.for()的作用
再來看看下面一段代碼
const a = Symbol('a')
const b = Symbol.for('a')
a === b // false
結果是false,與上面的區別僅僅在于第一個Symbol的創建方式,我們來分析。
1、使用Symbol(‘a’)直接創建,所以該Symbol(‘a’)不在全局注冊表中
2、使用Symbol.for(‘a’)在全局注冊表中尋找描述為a的Symbol,并沒有找到,所以在全局注冊表中又創建了一個描述為a的新的Symbol
3、秉承Symbol創建的唯一特性,所以a與b創建的Symbol不同,結果為false
Symbol.keyFor()獲取全局注冊表變量的描述
const a = Symbol('a')
const b = Symbol.for('a')
Symbol.keyFor(a) // undefined
Symbol.keyFor(b) // a
symbol對象不能用于數據運算,包括+、-、*、/等
const a = Symbol('a')
a+0 //Uncaught TypeError: Cannot convert a Symbol value to a number