1. 程式人生 > 其它 >ES6中的新資料型別——Symbol

ES6中的新資料型別——Symbol

今天小編和大家來聊一聊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