Symbol 类型
Symbol 類(lèi)型
1. Symbol 聲明
根據(jù)規(guī)范,對(duì)象的屬性鍵只能是字符串類(lèi)型或者 Symbol 類(lèi)型
Symbol 是一種基本數(shù)據(jù)類(lèi)型,Symbol()函數(shù)會(huì)返回 symbol 類(lèi)型的值,Symbol 值是唯一的標(biāo)識(shí)符,不會(huì)與其他屬性名產(chǎn)生沖突
Tips:Symbol 函數(shù)前不能使用 new 命令,會(huì)報(bào)錯(cuò)。這是因?yàn)樯傻?Symbol 是一個(gè)原始類(lèi)型的值,不是對(duì)象類(lèi)型
let symbol1 = Symbol(); let symbol2 = Symbol(); console.log(symbol1 === symbol2); // false2. Symbol 描述與轉(zhuǎn)換
2-1 description 描述
Symbol 函數(shù)可以接受一個(gè)字符串作為參數(shù),表示對(duì) Symbol 實(shí)例的描述
ES2019 提供了一個(gè)實(shí)例屬性 description,直接返回 Symbol 的描述
// Symbol接受一個(gè)字符串作為參數(shù) let sym = Symbol(1); // description來(lái)獲取Symbol描述 console.log(typeof sym.description); // [object String]如果 Symbol 的參數(shù)是一個(gè)對(duì)象,就會(huì)調(diào)用該對(duì)象的toString方法,將其轉(zhuǎn)為字符串,然后才生成一個(gè) Symbol 值
let obj = {toString() {return 'symbol';} } let sym1 = Symbol(obj); console.log(sym1.description); // symbol2-2 類(lèi)型轉(zhuǎn)換
-
Symbol 值不會(huì)發(fā)生隱式轉(zhuǎn)換,不會(huì)被自動(dòng)轉(zhuǎn)換為字符串
-
如果我們真的想顯示一個(gè) Symbol 值,可以通過(guò) toString() 顯式轉(zhuǎn)為字符串
-
Symbol 值也可以轉(zhuǎn)為布爾值,但是不能轉(zhuǎn)為數(shù)值
3. 作為屬性名
由于每一個(gè) Symbol 值都是不相等的,這意味著 Symbol 值可以作為標(biāo)識(shí)符,用于對(duì)象的屬性名,就能保證不會(huì)出現(xiàn)同名的屬性
- Symbol 作為對(duì)象屬性的三種寫(xiě)法
- Symbol 聲明和訪問(wèn)使用 [] 方括號(hào)形式操作,不能使用 . 點(diǎn)語(yǔ)法因?yàn)?. 點(diǎn)語(yǔ)法是操作字符串屬性的
下面寫(xiě)法是錯(cuò)誤的,會(huì)將 Symbol 屬性當(dāng)成字符串處理
let sym1 = Symbol(); let obj3 = {}; obj3.sym1 = 'hello' console.log(obj3[sym1]); // undefined console.log(obj3['sym1']); // hello- 在對(duì)象的內(nèi)部,使用 Symbol 值定義屬性時(shí),Symbol 值必須放在方括號(hào)之中
4. 屬性遍歷與復(fù)制
4-1 Symbol 屬性遍歷
Symbol 作為屬性名,遍歷對(duì)象時(shí)的情況:
- 不會(huì)出現(xiàn)在for...in、for...of 循環(huán)中
- Object.keys()、Object.getOwnPropertyNames()、JSON.stringify() 也會(huì)忽略 Symbol 屬性
- Object.assign 會(huì)同時(shí)復(fù)制字符串和 Symbol 屬性
4-2 獲取 Symbol 屬性
Object.getOwnPropertySymbols()
可以獲取指定對(duì)象的所有 Symbol 屬性名,該方法返回一個(gè)數(shù)組,數(shù)組元素是當(dāng)前對(duì)象的所有用作屬性名的 Symbol 值
let sym = Symbol('學(xué)習(xí)'); let sym1 = Symbol('努力'); let sym2 = Symbol('加油'); let obj = {[sym]: 'hello',[sym1]: 'hello1',[sym2]: 'hello2', } console.log(obj[sym]); // hello let symbolAll = Object.getOwnPropertySymbols(obj) console.log(symbolAll); // [Symbol(學(xué)習(xí)), Symbol(努力), Symbol(加油)]5. Symbol.for()、Symbol.keyFor() 全局
5-1 Symbol.for()
通常所有的 Symbol 都是不同的,即使它們有相同的名字,如果需要使用同一個(gè) Symbol 值,可以通過(guò) Symbol.for() 方法來(lái)實(shí)現(xiàn)
Symbol.for() 接受一個(gè)字符串作為參數(shù),然后搜索有沒(méi)有以該參數(shù)作為名稱的 Symbol 值
Tips: Symbol.for()、Symbol.keyFor() 都只獲取全局的 Symbol
- 如果有,就返回這個(gè) Symbol 值
- 否則就新建一個(gè)以該字符串為名稱的 Symbol 值,并將其注冊(cè)到全局
5-2 Symbol.for() 與 Symbol() 區(qū)別
- Symbol.for() —— 會(huì)被登記在全局環(huán)境中供搜索,不會(huì)每次調(diào)用就返回一個(gè)新的 Symbol 類(lèi)型的值,而是會(huì)先檢查給定的 key 是否已經(jīng)存在,如果不存在才會(huì)新建一個(gè)值
- Symbol() —— 不會(huì)被登記在全局環(huán)境中供搜索,每次調(diào)用都會(huì)返回一個(gè)不同的值
5-3 Symbol.keyFor()
Symbol.keyFor(sym) 通過(guò)全局 Symbol 返回一個(gè) Symbol 描述或者名字
如果 Symbol 不是全局的,它將無(wú)法找到它并返回 undefined
let sym = Symbol.for('hello'); let symkeyfor = Symbol.keyFor(sym); console.log(symkeyfor); // hello// 不是全局Symbol返回undefined let sym1 = Symbol('嘻嘻'); let symkeyfor1 = Symbol.keyFor(sym1); console.log(symkeyfor1); // undefined5-4 Reflect.ownKeys()
Reflect.ownKeys()方法可以返回所有類(lèi)型的鍵名,包括常規(guī)鍵名和 Symbol 鍵名
let str = 'haha'; let sym = Symbol('symbol') let obj = {name: 'jsx',[str]: 'haha',[sym]: 'symbol' } let allKeys = Reflect.ownKeys(obj) console.log(allKeys); // ['name', 'haha', Symbol(symbol)]6. Symbol 使用場(chǎng)景
6-1 解決對(duì)象同名屬性沖突
作為對(duì)象屬性 當(dāng)一個(gè)復(fù)雜對(duì)象中含有多個(gè)屬性的時(shí)候,很容易將某個(gè)屬性名覆蓋掉,利用 Symbol 值作為屬性名可以很好的避免這一現(xiàn)象
// let user1 = 'jsx';// let user2 = 'jsx';let user1 = Symbol('jsx');let user2 = Symbol('jsx');let obj = {[user1]: ['html', 'css', 'js'],[user2]: ['html', 'css', 'js', 'vue']}// 后面同名屬性覆蓋前面屬性// console.log(obj[user1]); // ['html', 'css', 'js', 'vue'] // console.log(obj[user2]); // ['html', 'css', 'js', 'vue']console.log(obj[user1]); // ['html', 'css', 'js'] console.log(obj[user2]); // ['html', 'css', 'js', 'vue']6-2 消除魔術(shù)字符串
當(dāng)在代碼之中多次出現(xiàn)、與代碼形成強(qiáng)耦合的某一個(gè)具體的字符串或者數(shù)值時(shí),可以通過(guò) Symbol 消除魔術(shù)字符串,改由含義清晰的變量代替
const TYPE_AUDIO = Symbol('audio') const TYPE_VIDEO = Symbol('video') const TYPE_IMAGE = Symbol('image')function handleFileResource(resource) {switch (resource.type) {case TYPE_AUDIO:console.log(resource)breakcase TYPE_VIDEO:console.log(resource)breakcase TYPE_IMAGE:preconsole.log(resource)breakdefault:console.log('錯(cuò)誤')} } handleFileResource({type: TYPE_AUDIO }) // {type: Symbol(audio)}6-3 對(duì)象屬性私有化
Symbol 作為對(duì)象屬性會(huì)隱藏自身屬性,Symbol 屬性不會(huì)被 for...in, Object.keys() 等等遍歷方法遍歷
let name = Symbol('jsx')function User() {this.lesson = ['jsx', 'ljj'];this.title = 'hello';this[name] = 'jsx'; } let user = new User(); console.log(user); // User {lesson: Array(2), title: 'hello', Symbol(jsx): 'jsx'} for (let item in user) {console.log(item); // lesson title }總結(jié)
- 上一篇: OS实验-模拟实现首次/最佳/最坏适应算
- 下一篇: 关于网络代理