JavaScript 引入 Symbol 类型的目的在于提供一个独一无二的标识符,防止属性名的冲突、实现更好的属性封装性,以及为对象属性定义一些非字符串形式的元数据。例如,在使用第三方库时,可能会担心属性名冲突,Symbol 可以确保每个属性都是独一无二的,这就大大减小了冲突的可能性。
详细来说,Symbol 作为一种新的原始数据类型,相对于字符串这种传统属性名,其不可变且唯一的特性使得对象属性能够拥有一个唯一的标识符。通过这种方式,开发者可以安全地扩展对象而不必担心属性名冲突,这在大型代码库或者多人协作的项目中尤其有用。
一、SYMBOL的概念与创建
Symbol 类型被引入 JavaScript 是在 ES6(ECMAScript 2015)中。每个 Symbol 都是完全唯一的,即便你使用相同的描述创建多个 Symbol,它们也是不同的。
创建一个 Symbol 非常简单,只需要调用 Symbol()
函数,并且可以选择性地提供一个描述字符串:
let sym1 = Symbol('my_symbol');
let sym2 = Symbol('my_symbol');
console.log(sym1 === sym2); // false
即使两个 Symbols 的描述是相同的,它们也是完全不同的。
Symbol 的主要特征就是它的唯一性,它通过这个特性提供了一种避免属性名冲突的方法,这在多个库或模块都试图向同一对象添加属性时非常有用。
二、SYMBOL在对象属性中的应用
Symbols 作为属性键来说,有几个特别的地方需要注意。
可以使用方括号语法将 Symbol 作为对象属性的键:
let mySymbol = Symbol();
let obj = {
[mySymbol]: 'value'
};
console.log(obj[mySymbol]); // 'value'
由于 Symbol 不会与任何其他属性键冲突,因此它经常被用来表示一些非公开的、元数据等属性。
默认情况下,使用 Symbol 作为键的属性不会出现在 for...in
、for...of
循环或 Object.keys()
、Object.getOwnPropertyNames()
方法返回的数组中。但是,它可以通过 Object.getOwnPropertySymbols()
方法来获取。
三、SYMBOL的内置值
ES6 引入的一些内置 Symbol 值,它们被称为“众所周知的 Symbols”。它们有特定的用途,并被赋予了对应的语义。
Symbol.iterator
这是一个用于定制对象的迭代行为的 Symbol。定义时,需要给对象设置一个返回迭代器的方法:
let collection = {
items: [],
*[Symbol.iterator]() {
for (let item of this.items) {
yield item;
}
}
};
还有如 Symbol.match
、Symbol.replace
等 Symbols,用于定制对象的基本行为,以上仅列举部分。
四、SYMBOL的全局注册表
有时,我们希望能在不同的代码片段或甚至是不同的 iframe/windows 中共享某些 Symbols。为此,ES6 提供了一个全局 Symbol 注册表。
Symbol.for()
利用 Symbol.for()
方法,可以创建一个全局的 Symbol。它在全局的范围内检查并注册 Symbol:
let globalSym = Symbol.for('app.global');
console.log(Symbol.for('app.global') === globalSym); // true
五、SYMBOL和JSON字符串化
当你尝试将一个对象进行 JSON 序列化时,Symbol 作为键的属性会被完全忽略:
let json = JSON.stringify({[Symbol('foo')]: 'bar'});
console.log(json); // '{}'
这意味着 Symbol 数据在经过 JSON.stringify()
处理时不会被包含在内。
六、SYMBOL的使用场景与实践
Symbol 类型的加入为 JavaScript 程序设计提供了新的可能性,以下是一些实际使用场景。
由于 Symbol 类型不是一个字符串,因此可以使用 Symbol 作为对象的键来避免因为动态属性访问而受到的 XSS 攻击。
在类的构造中,利用 Symbol 不可枚举的特性,可以模拟私有变量:
let _counter = Symbol();
let _action = Symbol();
class MyClass {
constructor(counter) {
this[_counter] = counter;
}
[_action]() {
// internal action
}
}
综上所述,Symbol 类型的引入解决了关于属性命名冲突的问题,尤其在组件化开发和大型应用中显示其价值。同时它的一些内建特性也使得它在处理对象的元编程方面发挥了作用。由于 Symbol 类型的唯一性和不可变性,它在现代 JavaScript 编程中常被用于表示独特的属性键、实现对象的内部状态和封装性、以及在编写可维护性更高和具有更佳隐私的代码方面发挥重要作用。
为什么 JavaScript 引入了 Symbol 类型?
Symbol.iterator
和 Symbol.toStringTag
,可以用于定义对象的默认迭代器或自定义对象的字符串表示形式。Symbol 类型有什么特点和用途?
Symbol.iterator
属性为一个函数,可以使对象支持迭代操作。这样可以方便地通过 for...of
循环遍历对象。Symbol.species
和 Symbol.toPrimitive
等。开发者可以借助这些符号常量来定制对象的行为。Symbol 类型如何与其他数据类型互操作?
toString
方法,将其转换为字符串类型。String()
函数进行强制类型转换。类似地,使用 Number()
函数可以将 Symbol 类型的值转换为数字类型,但结果通常是不可用的。版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系邮箱:hopper@cornerstone365.cn 处理,核实后本网站将在24小时内删除。