你知道的Symbol

104 阅读4分钟

「这是我参与2022首次更文挑战的第37天,活动详情查看:2022首次更文挑战

Symbol 中文意思就是符号。是es6新出的原始数据类型。 Symbol这个函数也不是构造函数,不支持new操作符

个人认为symbol有两点十分突出:

一是必定独一无二,一个代码块内不可能有两个相同的symbol;

二是不可描述,这里指你无法直接看到它,不像数字、字符、逻辑值那样。

根据第一个特点,人们用它来解决唯一性问题, 比如属性冲突。 但是 注意,由于它的不可直观性,你必须声明一个变量来存储它,它治不了起名困难症

言归正传,先来看看创建。

创建

创建就是直接调用 Symbol函数,再次强调不能new,毕竟它是个原始数据类型。

它接受一个参数,作为这个符号的描述。这个参数不影响符号的生成,就是说即便两个符合的描述一致,它两也不一样

image.png

这个描述的主要作用就是在转字符和控制台打印(实际上就会转字符)的时候便于区分。

image.png

类型转换

刚才已经试过了可以转字符串。

转逻辑值自然也是可以的

转数字就不行了。

并且只能显式转换, 不能背地里偷着转换。 否则会出错。

image.png

作为键

先前我们就知道了,可以用符合作为独一无二的属性名。

但是,由于其不可描述性, 你不能直接用点语法来访问这个属性。 实际上,用符号作为键,这个属性就是一个不可遍历(enumerable:false)的属性。所谓不可遍历就是说,一般的for in Object.entries,keys,都无法获取这个属性。虽然,我们用getOwnPropertyDescriptors(),在控制台上看到了这个属性,但是它仍然是一个对象的键,你还是无法直接拿到。

image.png

也因此,有人用符号实现私有属性方法。

获取符号键

那么我们就真的拿不到了吗? 不,还是天无绝人之路。有一个专门的方法,用于获取对象的符号键。

它就是Object.getOwnPropertySymbols,其返回值是一个数组,我们遍历数组就能获取全部符合键。 但是你实际上还是不知道哪个是哪个,只能通过转字符查看其描述。

image.png

除此之外,我们的映射Reflect(它上面的方法真多,有啥不好解决的就可以尝试找他)上也有一个方法可以获取全部属性(包括不可遍历的和符号)。Reflect.ownKeys

image.png

你可能知道的Symbol.for 和 Symbol.keyFor

这个方法和Symbol本身很像,也是接收一个描述,返回一个符号。

for

这个for,可以理解为 look for。就是查找,查找已经存在的符合描述的symbol,如果没有声明过有这种描述的symbol,那么就会创建一个新的并返回。

但是其查找范围仅限于使用Symbol.for声明的符号,也就是说如果你是用Symbol(1)生成的符号,用 Symbol.for(1)是找不到的,它会返回一个新的符号,如果你再次调用Symbol.for(1),就会返回之前的那个符号。

image.png

keyFor

这个方法就是配套 for方法使用的,它接受一个符号参数,返回这个符号的描述。 其范围同样仅限于 for方法创建的符号。

image.png

你可能不知道Symbol上挂了一堆属性

image.png 我们捡几个比较容易理解的或者可能会用到的。

  • iterator Symbol.iterator这属性指向的是对象的迭代器,如果要自定义对象的迭代器就用这个作为其方法名。

image.png

然后,有很多都是默认方法,我们平常也在用,只不过不是直接使用。

  • hasInstance 这个方法会在 使用 instanceof 操作符时调用。 a instanceof A,就会调用ASymbol.hasInstance。 我们可以显示定义这个函数来改变 instanceof的默认操作 。

image.png

symbol的回顾就到这里。

最后

一定要注意 symbol是原始值类型。

应用主要就是利用其唯一性, 例如要定义几个枚举类型,然后就是自定义迭代器。其他的黑科技用的就少一些。