「这是我参与2022首次更文挑战的第37天,活动详情查看:2022首次更文挑战」
Symbol 中文意思就是符号。是es6新出的原始数据类型。 Symbol这个函数也不是构造函数,不支持new操作符。
个人认为symbol有两点十分突出:
一是必定独一无二,一个代码块内不可能有两个相同的symbol;
二是不可描述,这里指你无法直接看到它,不像数字、字符、逻辑值那样。
根据第一个特点,人们用它来解决唯一性问题, 比如属性冲突。 但是 注意,由于它的不可直观性,你必须声明一个变量来存储它,它治不了起名困难症。
言归正传,先来看看创建。
创建
创建就是直接调用 Symbol
函数,再次强调不能new,毕竟它是个原始数据类型。
它接受一个参数,作为这个符号的描述。这个参数不影响符号的生成,就是说即便两个符合的描述一致,它两也不一样。
这个描述的主要作用就是在转字符和控制台打印(实际上就会转字符)的时候便于区分。
类型转换
刚才已经试过了可以转字符串。
转逻辑值自然也是可以的
转数字就不行了。
并且只能显式转换, 不能背地里偷着转换。 否则会出错。
作为键
先前我们就知道了,可以用符合作为独一无二的属性名。
但是,由于其不可描述性, 你不能直接用点语法来访问这个属性。 实际上,用符号作为键,这个属性就是一个不可遍历(enumerable:false)的属性。所谓不可遍历就是说,一般的for in Object.entries,keys
,都无法获取这个属性。虽然,我们用getOwnPropertyDescriptors()
,在控制台上看到了这个属性,但是它仍然是一个对象的键,你还是无法直接拿到。
也因此,有人用符号实现私有属性方法。
获取符号键
那么我们就真的拿不到了吗? 不,还是天无绝人之路。有一个专门的方法,用于获取对象的符号键。
它就是Object.getOwnPropertySymbols
,其返回值是一个数组,我们遍历数组就能获取全部符合键。 但是你实际上还是不知道哪个是哪个,只能通过转字符查看其描述。
除此之外,我们的映射Reflect(它上面的方法真多,有啥不好解决的就可以尝试找他)上也有一个方法可以获取全部属性(包括不可遍历的和符号)。Reflect.ownKeys
你可能知道的Symbol.for 和 Symbol.keyFor
这个方法和Symbol
本身很像,也是接收一个描述,返回一个符号。
for
这个for,可以理解为 look for。就是查找,查找已经存在的符合描述的symbol,如果没有声明过有这种描述的symbol,那么就会创建一个新的并返回。
但是其查找范围仅限于使用Symbol.for声明的符号,也就是说如果你是用Symbol(1)
生成的符号,用 Symbol.for(1)
是找不到的,它会返回一个新的符号,如果你再次调用Symbol.for(1)
,就会返回之前的那个符号。
keyFor
这个方法就是配套 for方法使用的,它接受一个符号参数,返回这个符号的描述。 其范围同样仅限于 for方法创建的符号。
你可能不知道Symbol上挂了一堆属性
我们捡几个比较容易理解的或者可能会用到的。
- iterator
Symbol.iterator
这属性指向的是对象的迭代器,如果要自定义对象的迭代器就用这个作为其方法名。
然后,有很多都是默认方法,我们平常也在用,只不过不是直接使用。
- hasInstance
这个方法会在 使用 instanceof 操作符时调用。
a instanceof A
,就会调用ASymbol.hasInstance。 我们可以显示定义这个函数来改变 instanceof的默认操作 。
symbol的回顾就到这里。
最后
一定要注意 symbol是原始值类型。
应用主要就是利用其唯一性, 例如要定义几个枚举类型,然后就是自定义迭代器。其他的黑科技用的就少一些。