学习笔记 JavaScript ES6 Symbol

学习内容

  • Symbol是新的原型数据类型
  • 声明方式
  • 应用场景

单词释义

Symbol:(独一无二的)

n. 象征,代表; 标志; 符号,记号

JS七个原始数据类型

undefine、null、number、string、boolean、object、symbol

Symbol是新的原型数据类型

第一种声明方式:

let s1 = Symbol()
let s2 = Symbol()
let s3 = Symbol('three') // 传入字符串用于对symbol的描述
let s4 = Symbol('four')
console.log(s1)
console.log(s2)
console.log(s1 === s2)

console.log(s3)
console.log(s4)
console.log(s3 === s4)

-------------------------
Symbol()
Symbol()
false
Symbol(three)
Symbol(four)
false

第二种声明方式

当参数是对象的时候,会自动调用该对象的toString方法,转化成一个字符串,再生成一个symbol的值:

const obj = {
    name : 'Sure'
}
console.log(Symbol(obj))

const obj1 = {
    name : 'Sure',
    toString() { // 对象内部function的简写形式
        return this.name
    }
}

console.log(Symbol(obj1))

------------------------------------------
Symbol([object Object])
Symbol(Sure) // 自动调用了obj1中的toString()


不能像声明对象的方法去声明Symbol(),比如:


let s = Symbol()
s.name = 'aaa'
console.log(s)

-------------------------------------------
Symbol() // 什么都没有,因为symbol不是一个对象

Symbol可以理解为不能重复的字符串,就是把它理解成字符串就行。

下面看一个symbol的API:

let s = Symbol()
let t = Symbol('desc')

console.log(s.description)
console.log(t.description)

------------------------
undefined
desc

第三种声明方式

let s1 = Symbol.for('orion')
let s2 = Symbol.for('orion')

console.log(s1 === s2)

-----------
true

上面代码中s1和s2相等,是因为这样的声明方式是全局的,当再次现出Symbol.for('orion')时,会去全局中查找是否有Symbol.for('orion'),如果有,就把值赋给s2。

再看把symbol.for写在方法内部,发现也是在全局中存在的:

function test() {
    return Symbol.for('test')
}

const x = test()
const y = Symbol.for('test')

console.log(x === y)

------------
true

与Symbol.for对应的还有一个Symbol.keyFor,作用是返回一个已经全局登记的Symbol类型的key:

let s1 = Symbol('test')
console.log(Symbol.keyFor(s1))

let s2 = Symbol.for('test')
console.log(Symbol.keyFor(s2))

----------------------------------------
undefined // Symbol('test')不属于全局定义
test // 使用全局定义

Symbol应用场景一:

班级中有重名的同学

下面这种写法,第二个李四把第一个李四覆盖掉了:


const grade = {
    李四: {addr : 'aaa', tel : 'bbb'},
    李四: {addr : 'ccc', tel : 'ddd'}
}

console.log(grade)
--------------------------------
李四: {addr: 'ccc', tel: 'ddd'}

下面这种写法,把key用变量表示,还是会有覆盖的情况:

const stu1 = '李四'
const stu2 = '李四'
const grade = {
    [stu1] : {addr : 'aaa', tel : 'bbb'},
    [stu2]: {addr : 'ccc', tel : 'ddd'}
}

console.log(grade)

-------------------------------
李四: {addr: 'ccc', tel: 'ddd'}

用Symbol作为key,保证key不冲突

这时Symbol的作用就体现出来了,两个李四全都可以输出:

const stu1 = Symbol('李四')
const stu2 = Symbol('李四')
const grade = {
    [stu1] : {addr : 'aaa', tel : 'bbb'},
    [stu2]: {addr : 'ccc', tel : 'ddd'}
}

console.log(grade)
console.log(grade[stu1]) // grade[stu1] 等价于 grade.key
console.log(grade[stu1])

---------------------------------------
Symbol(李四): {addr: 'aaa', tel: 'bbb'}
Symbol(李四): {addr: 'ccc', tel: 'ddd'}
{addr: 'aaa', tel: 'bbb'}
{addr: 'aaa', tel: 'bbb'}

Symbol应用场景二:

一定程度上可以保护类中的某些属性,比如使用for in无法遍历出对象中的symbol属性

const sym = Symbol('syu6')
class User {
    constructor(name) {
        this.name = name
        this[sym] = 'syu.com'
    }

    getName() {
        return this.name + this[sym]
    }
}
const user = new User('Sure')
// console.log(user.getName())

// 使用for in遍历对象的属性
for(let key in user) { // 无法取得symbol属性
    console.log(key)
}

for(let key of Object.keys(user)) { // 无法取得symbol属性
    console.log(key)
}

for(let key of Object.getOwnPropertySymbols(user)){ // 只能取到symbol属性
    console.log(key)
}
console.log('-------------')
for(let key of Reflect.ownKeys(user)) { // 普通属性和symbol属性都可以取到
    console.log(key)
}
----------------------------------
name
name
Symbol(syu6)
-------------
name
Symbol(syu6)

Symbol应用场景三:

消除魔术字符串

魔术字符串是指多次出现,被多次引用,每次都手写的话容易出错:

function getArea(shape) {
    let area = 0
    switch(shape) {
        case 'Triangle' : 
            arae = 1
            break
        case 'Circle' :
            area = 2
            break
    }
    return area
}
console.log(getArea('Triangle')) // 这里的'Triangle'就是魔术字符串,写两次很麻烦,还容易出错

看下面的实现方式就好很多:

const shapeType = {

    // triangle : 'Triangle',
    // circle : 'Circle'

    // 把上面两行改为下面这样,其实我们并不关心symbol()是什么,主要是key就可以说明我们想的东西了
    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)) // 这里的'Triangle'就是魔术字符串,写两次很麻烦,还容易出错

---------
1

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值