关于ES6 Symbol类型的小帖士

先来看看Symbol函数的定义:

1
Symbol(description?) → symbol

接收一个描述(描述可以为undefined),返回一个symbol类型的变量。
然后有意思的来了,首先传进去的参数只是个描述,给读代码的人看的,和返回值无关,Symbol函数每次都返回一个不一样的symbol类型变量,像这样:

1
2
3
4
5
6
7
8
9
> Symbol() === Symbol()
false

> Symbol("a") === Symbol("a")
false

> let a = Symbol("this is a")
> a === a
true

不过要注意的是,symbol类型虽然是一个基本类型,但是一般来说不被json格式支持,不要试图在json格式里使用它,像这样([k]的含义是用k的内容作为对象键-值对的键而不是用k这个字符串作为键):

1
2
3
4
> let k = Symbol("key")
> let obj = {[k]: 5}
> JSON.stringify(obj)
{}

这导致了nodejs的REPL打印对象的时候会漏掉以symbole作为键的内容,像这样:

1
2
3
4
> let k = Symbol("key")
> let obj = {[k]: 5, d: 6}
> obj
{ d: 6 }

不过直接访问是没有问题的:

1
2
3
4
> let k = Symbol("key")
> let obj = {[k]: 5, d: 6}
> obj[k]
5

所以Symbol最大的用处是用来做常量定义,相比:

1
const ERROR = "error"

使用Symbol

1
const ERROR = Symbol("error")

会更好一些,比如你有两个包log和print,它们的ERROR常量其实不是一回事,用Symbol就会很清晰:

1
2
> log.ERROR === print.ERROR
false