FE-DSHUI / DSHUI

前端王者小分队读书会
4 stars 1 forks source link

《你不知道的JavaScript(下卷)》-理解symbol-2021-05-27 #92

Open AwakenedSomeone opened 3 years ago

AwakenedSomeone commented 3 years ago

关于Symbol之前已经说过了,但是自己还是有些不太理解其用途和用法。现重新理解一下:

  1. 首先创建一个symbol:
    var sym = Symbol('hello')
    typeof sym   // "symbol"

    如上所示创建了一个Symbol变量,并传入了一个值:hello。那么这个sym就是一个符号,符号的内部值(不是hello,是隐藏的一个独一无二的值),也可以称为它的名称(name),它是不在代码中出现且无法获得的,那么这个符号隐藏的值无法获取,存在的意义是什么?

符号的主要意义是创建一个类似字符串的不会与其他任何值冲突的值,考虑使用一个符号作为事件名的常量表示的例子: const EVT_LOGIN = Symbol('event.login') 然后再需要像‘event.login’这样的一般字符串字面量的地方就可以使用EVT_LOGIN了

evthub.listen(EVT_LOGIN, function(data) { 
    // ... 
})

这样做的好处是分化处理事件不会有任何混淆。 但如何evthub里需要把EVT_LOGIN当做真正的字符串使用,那么需要使用String()或者toString()进行显示转换,不允许隐式转换符号为字符串。

  1. 全局符号注册: 使用如下:

    const EVT_HUB = Symbol.for('event.login')
    console.log(EVT_LOGIN)               // Symbol(event.login)

    Symbol.for(...)在全局符号注册表中搜索,查看是否有描述文字相同的符号已经存在,如果有的话,就返回它,没有就新建一个并将其返回。意味着只要使用的描述名称匹配,可以在应用的任何地方通过Symbol.for(...)从注册表中获取这个符号。

  2. 通过 Symbol.keyFor(...)获取符号的描述文本,可以利用获得的描述文本再次取得符号: const s = Symbol.for('something cool') var desc = Symbol.keyFor(s) console.log(desc) // "something cool"

//再次从注册中取得符号 var s2 = Symbol.for(desc) s2 === s // true

  1. 对象属性中使用Symbol
    
    var o = {
    foo: 42,
    [Symbol("bar")]: "hello world",
    baz: true
    }

Object.getOwnPropertyNames(o) // ["foo", "baz"] // 取得对象的符号属性 Object.getOwnPropertySymbols(o) // [Symbol(baz)]


由此可以看出,对象的属性符号实际上并不是隐藏或不可访问的,因为总可以通过Object.getOwnPropertySymbols(..)列表看到
5. 内置符号
 ES6支持若干预定义的内置符号,但是不是像全局符号那样注册在全局符号表里,而是作为Symbol对象的属性保存,比如:
Symbol.iterator