今天小編和大家來聊一聊es6中新增的一個原始資料型別Symbol。在es5中原始資料型別(基本資料型別)有以下六種:Undefind、Null、Bool、 String、Number、Object。今天結合例項和大家一起探討一下這個神奇的Symbol。大家也可以關注我的微信公眾號,蝸牛全棧。
一、基本宣告方式
1、方式一
let s1 = Symbol()
let s2 = Symbol()
console.log(s1) // Symbol{}
console.log(s2) // Symbol{}
console.log(s1 === s2) // false 說明每一個Symbol用這種方式宣告都是與眾不同的。後續會有應用
2、方式二
let s1 = Symbol('foo')
let s2 = Symbol('bar') console.log(s1) // Symbol(foo)
console.log(s2) // Symbol(bar)
console.log(s1 === s2) // false
const obj = {
name:"lilei",
toString(){
return this.name
}
}
let s = Symbol(obj) // 如果引數是Object的時候,會自動呼叫該物件的toString方法
console.log(s) // Symbol(lilei)
3、關於description
let s = Symbol()
s.name = "lilei"
console.log(s) // Symbol{} // Symbol不是物件,不能用對待物件的方式對待Symbol
console.log(s.description) // undefind
console.log(s.name) // undefind
let s = Symbol('foo')
console.log(s.description) // foo
二、Symbol.for:通過Symbol.for相當於定義在全域性的變數,如果之前宣告過,後面再通過Symbol.for的時候,會在全域性找,如果描述一樣的話,會和上一個一樣。可以簡單理解為物件指向同一個堆記憶體地址。
let s1 = Symbol.for('foo')
let s2 = Symbol.for('foo')
console.log(s1) // Symbol(foo)
console.log(s1 === s2) // true
// 即使是在函式定義域內,通過Symbol.for也會將該Symbol註冊在全域性
function foo(){
return Symbol.for('foo')
} const x = foo()
const y = Symbol.for('foo')
console.log(x === y) // true
三、Symbol.keyFor:檢視是否在全域性登記Symbol裡面的描述。與上面的Symbol.for對應。
const s1 = Symbol('foo')
console.log(Symbol.keyFor(s1)) // undefind
const s2 = Symbol.for('foo')
console.log(Symbol.keyFor(s1)) // foo
四、實際應用:
應用一:解決物件中key重複但是表示不同資訊的情況
// 物件對於相同的key的資訊會進行覆蓋
const grade = {
zhangsan:{
address:"xxx",tel:"111"
},
lisi:{
address:"yyy",tel:"222"
},
lisi:{
address:"zzz",tel:"333"
},
} console.log(grade) // {zhangsan:{address:"xxx",tel:"111"},lisi:{address:"zzz",tel:"333"}}
// 通過變數構建物件
const stu1 = "lisi"
const stu2 = "lisi"
const grade = {
[stu1]:{
address:"yyy",tel:"222"
},
[stu2]:{
address:"zzz",tel:"333"
},
}
console.log(grade) // {lisi:{address:"zzz",tel:"333"}}
// es6通過Symbol解決key相同,資訊不同情況
const stu1 = Symbol("lisi")
const stu2 = Symbol("lisi")
const grade = {
[stu1]:{
address:"yyy",tel:"222"
},
[stu2]:{
address:"zzz",tel:"333"
},
}
console.log(grade) // {Symbol(lisi):{address:"yyy",tel:"222"},Symbol(lisi):{address:"zzz",tel:"333"}}
console.log(grade[stu1]) // {address:"yyy",tel:"222"}
應用二:保護類中的部分屬性
// 定義基本類和類中方法呼叫
class User{
constructor(name){
this.name = name
}
getName(){
return this.name
}
} const user = new User("lilei")
console.log(user.getName()) // lilei
// 不同迴圈遍歷方式獲取類內部屬性,根據是否可以獲取Symbol作為key的情況
const sym = Symbol("AILI")
class User{
constructor(name){
this.name = name
this[sym] = "AILI.com"
}
getName(){
return this.name + this[sym]
}
} const user = new User("lilei")
console.log(user.getName()) // lileiAILI.co// 通過for...in 無法遍歷到Symbol屬性
for(let key in user){
console.log(key) // name
} // 同樣不能獲取到Symbol屬性
for(let key of Object.keys(user)){
console.log(key) // name
}
// 只能取到Symbol屬性
for(let key of Object.getOwnPropertySymbols(user)){
console.log(key) // Symbol(AILI)
} // 即能獲取到普通屬性,又能獲取到Symbol屬性
for(let key of Reflect.ownKeys(user)){
console.log(key) // name Symbol(AILI)
}
應用三:消除魔法字串(比較長或者難以辨認,容易出錯的字串)
// 函式實現基本功能,函式中【Triangle】和【Circle】比較容易出錯
function getArea(shape){
let area = 0
switch(shape){
case "Triangle":
area = 1
break
case "Circle":
area = 2
break
}
return area
}
console.log(getArea("Triangle")) // 1
// 通過物件,將魔法字串初步隱藏
const shapeType = {
triangle:"Triangle",
circle:"Circle"
}
function getArea(shape){
let area = 0
switch(shape){
case shapeType.triangle:
area = 1
break
case shapeType.circle:
area = 2
break
}
return area
}
console.log(getArea(shapeType.triangle)) // 1
// 在這個函式中,【Triangle】和【Circle】已經不重要,只要區分開即可,利用Symbol不一致性
const shapeType = {
triangle:Symbol(),
circle:Symbol()
}
function getArea(shape){
let area = 0
switch(shape){
case shapeType.triangle:
area = 1
break
case shapeType.circle:
area = 2
break
}
return area
}
console.log(getArea(shapeType.triangle)) // 1