ES6基础:Symbol

概述

ES5 的对象属性名都是字符串,这容易造成属性名的冲突。比如,你使用了一个他人提供的对象,但又想为这个对象添加新的方法(mixin 模式),新方法的名字就有可能与现有方法产生冲突。如果有一种机制,保证每个属性的名字都是独一无二的就好了,这样就从根本上防止属性名的冲突。这就是 ES6 引入Symbol的原因。

ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值。它属于 JavaScript 语言的原生数据类型之一,其他数据类型是:数值(Number)、字符串(String)、布尔值(Boolean)、nullundefined、对象(Object)、大整数(BigInt)。

Symbol 值通过Symbol()函数生成。

上面代码中,变量s就是一个独一无二的值。typeof运算符的结果,表明变量s是 Symbol 数据类型,而不是字符串之类的其他类型。

注意,Symbol()函数前不能使用new命令,否则会报错。这是因为生成的 Symbol 是一个原始类型的值,不是对象,所以不能使用new命令来调用。另外,由于 Symbol 值不是对象,所以也不能添加属性。基本上,它是一种类似于字符串的数据类型。

Symbol()函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述。

上面代码中,s1s2是两个 Symbol 值。如果不加参数,它们在控制台的输出都是Symbol(),不利于区分。有了参数以后,就等于为它们加上了描述,输出的时候就可以分清是哪个值。

注意,Symbol()函数的参数只是表示对当前 Symbol 值的描述,因此相同参数的 Symbol 函数的返回值是不相等的。

上面代码中,s1s2都是Symbol()函数的返回值,而且参数相同,但是它们是不相等的。

Symbol 值不能与其他类型的值进行运算,会报错。

Symbol.prototype.description

Symbol()函数创建 Symbol 值时,可以用参数添加一个描述。但是,读取这个描述需要将 Symbol 显式转为字符串。

上面的用法不是很方便。ES2019 提供了一个 Symbol 值的实例对象description,直接返回 Symbol 值的描述。

作为属性名的 Symbol

由于每一个 Symbol 值都是不相等的,这意味着只要 Symbol 值作为标识符,用于对象的属性名,就能保证不会出现同名的属性。

上面代码通过方括号结构和Object.defineProperty()方法,将对象的属性名指定为一个 Symbol 值。

注意,Symbol 值作为对象属性名时,不能使用点运算符。Symbol 值必须放在方括号中。

属性名的遍历

Symbol 值作为属性名,遍历对象的时候,该属性不会出现在for...infor...of循环中,也不会被Object.keys()Object.getOwnPropertyNames()JSON.stringify()返回。

但是,它也不是一个私有属性,有一个Object.getOwnPropertySymbols()方法,可以获取指定对象的所有 Symbol 属性名。该方法返回一个数组,成员是当前对象的所有用作属性名的 Symbol 值。

另一个新的 API,Reflect.ownKes()方法可以返回所有类型的键名,包括常规键名和 Symbol 键名。

Symbol.for(),Symbol.keyFor()

Symbol.for()方法接受一个字符串作为参数,然后搜索有没有以该参数作为名称的 Symbol 值。如果有,就返回这个 Symbol 值,否则就新建一个以该字符串为名称的 Symbol 值,并将其注册到全局。

上面代码中,s1s2都是 Symbol 的值,但是它们都是由同样参数Symbol.for方法生成的,所以实际上是一个值。

Symbol.for()Symbol()的区别是,前者会被登记在全局环境中供搜索,后者不会。

Symbol.keyFor()方法返回一个已登记的 Symbol 类型值得key

上面代码中,变量s2属于未登记的 Symbol 值,所以返回undefined

内置的 Symbol 值

Symbol.hasIntance

Symbol.isConcatSpreadable

Symbol.species

Symbol.match

Symbol.replace

Symbol.search

Symbol.split

Symbol.iterator

Symbol.toPrimitive

Symbol.toStringTag

Symbol.unscopables

原创文章,作者:seabert,如若转载,请注明出处:https://bysjb.cn/symbol.html