📜  在 ES6 中引入符号的动机(1)

📅  最后修改于: 2023-12-03 15:07:39.120000             🧑  作者: Mango

在 ES6 中引入符号的动机

ES6 中引入符号这一概念的主要动机,是为了解决对象属性名冲突的问题。

在 ES5 中,我们通常会将一些特殊属性名用字符串表示,例如:

var obj = {};
obj['foo'] = 'bar';

但是字符串作为属性名有一个明显的缺点:容易冲突。很多时候,我们不知道属性名是否已经被使用过,尤其是在多人协作的大型项目中。

为了解决这个问题,ES6 引入了符号(Symbol)这一概念。每个符号都是唯一的,可以用来作为对象的属性名。例如:

var obj = {};
var foo = Symbol('foo');
obj[foo] = 'bar';

这样,即使有其他属性名为 'foo' 的属性,也不会影响符号作为属性名的唯一性。

符号的创建和使用

通过 Symbol 函数可以创建一个符号值,例如:

var foo = Symbol('foo');

每次调用 Symbol 函数都会创建一个新的符号值。参数是可选的,用于提示符号的用途,方便调试。

可以使用方括号语法或点语法来访问具有符号属性名的对象属性,例如:

var obj = {};
var foo = Symbol('foo');
obj[foo] = 'bar';
console.log(obj[foo]); // 输出 'bar'
console.log(obj.foo); // 输出 undefined

注意,点语法不能用于访问具有符号属性名的对象属性。

全局符号和本地符号

符号分为两种:全局符号和本地符号。

全局符号可以在整个应用程序中使用,例如:

var foo = Symbol.for('foo');

Symbol.for 函数会首先检查全局符号表中是否存在指定名称的符号,如果存在就返回该符号,否则就创建一个新的全局符号并返回。这样做可以保证符号的全局唯一性。

本地符号则仅在当前代码块中有效。

内置符号

ES6 中还定义了许多内置的符号,用于表示对象的一些特殊行为。例如:

  • Symbol.iterator: 对象的默认迭代器(可以通过 obj[Symbol.iterator]() 方法调用)。
  • Symbol.toStringTag: 对象的自定义类型标记。
  • Symbol.hasInstance: 对象是否为某个类的实例。
  • Symbol.species: 当前对象引用的构造函数。
  • Symbol.match: 用于字符串匹配的正则表达式。
  • 等等。

这些内置符号可以帮助我们更方便、更准确地控制对象的行为。

总结

引入符号的主要动机是为了解决对象属性名冲突的问题。符号是唯一的,可以用来作为对象的属性名。ES6 定义了许多内置符号,用于表示对象的一些特殊行为。符号分为全局符号和本地符号,可以通过 Symbol.for 函数创建全局符号。使用符号可以更方便、更准确地控制对象的行为。