无论如何,什么是符号? ð
符号是Ecmascript 6(ES6)中引入的原始数据类型,为语言添加了新的功能层。与字符串或数字不同,符号是独特且不可变的,非常适合创建隐藏的对象属性或充当唯一的标识符。它们就像神奇的西吉尔人一样,每个西吉尔都代表一个独特的概念。
const magicSymbol = Symbol('I am a magic symbol!');
传递给Symbol()
的参数仅仅是一个描述,有助于调试和标识,但不会影响符号的独特性。
独特性和身份ð
符号最引人注目的品质之一就是它们的独特性。两个具有相同描述的符号仍然是不同的实体。
const symbol1 = Symbol('key');
const symbol2 = Symbol('key');
console.log(symbol1 === symbol2); // false
在避免在各种情况下(例如定义对象属性或实现自定义迭代器)命名碰撞时,此特征特别有价值。
隐藏特性
想象拥有大多数操作中隐藏的属性,避免了意外替代。符号恰恰提供了功能。
const hiddenProperty = Symbol('hidden');
const myObject = {
[hiddenProperty]: 'I am hidden!',
visibleProperty: 'You can see me.',
};
console.log(myObject.visibleProperty); // "You can see me."
console.log(myObject[hiddenProperty]); // "I am hidden!"
元数据的符号
符号非常适合将元数据固定到不加定常规属性的物体上。
const metaDataSymbol = Symbol('metadata');
class MagicalSpell {
constructor(name) {
this.name = name;
this[metaDataSymbol] = 'Contains powerful magic!';
}
}
const spell = new MagicalSpell('Levitation');
console.log(spell[metaDataSymbol]); // "Contains powerful magic!"
众所周知的符号ð
-
Symbol.iterator
:用于定义对象的默认迭代器。 -
Symbol.toStringTag
:确定Object.prototype.toString()
方法使用的默认描述。 -
Symbol.species
:控制用于创建派生对象的构造函数。 -
Symbol.hasInstance
:自定义instanceof
操作员的行为。
优点ð¥
封装和隐私:符号允许开发人员创建隐藏的属性,保护关键数据免于无意访问或修改。
唯一性和安全性:符号唯一性可确保属性不会意外碰撞,减少错误和意外副作用。
元数据没有干扰:可以使用符号将元数据连接到物体上,而不会干扰常规属性,维护清洁和有组织的代码。
增强内置对象:JavaScript的知名符号可以增强对象的行为而不会改变其基本结构。
限制
虽然符号为JavaScript带来了一些巫术,但它们并不是所有情况的解决方案。由于它们不是通过枚举暴露的,因此像for...in
循环这样的常见对象迭代技术不会捕获符号属性。但是,Object.getOwnPropertySymbols()
方法允许检索。