在 ES8/ES2017 中,引入了两种新的符号类型:类型名称符号和 well-known symbol。这些符号提供了一种更加灵活和可定制的方式来定义对象的行为。在本文中,我们将深入探讨这些符号类型,了解它们的工作原理以及如何使用它们来提高代码的可读性和可维护性。
类型名称符号
类型名称符号是一种新的符号类型,用于定义对象的类型名称。这些符号通常用于定义自定义对象或类的类型名称,以便在调试和日志记录时更容易识别它们。
类型名称符号的语法如下:
const myType = Symbol.for('myType');
在这个例子中,我们使用 Symbol.for
方法创建了一个名为 myType
的类型名称符号。接下来,我们可以将这个符号用作对象的属性名或方法名,以便在代码中引用它。
例如,我们可以创建一个自定义的 Person
类,并使用类型名称符号来标识它的类型名称:
// javascriptcn.com 代码示例 const PersonType = Symbol.for('Person'); class Person { constructor(name, age) { this.name = name; this.age = age; } [PersonType]() { return 'I am a person'; } } const person = new Person('John', 30); console.log(person[PersonType]()); // 输出:I am a person
在这个例子中,我们使用 Symbol.for
方法创建了一个名为 PersonType
的类型名称符号,并将其用作 Person
类的方法名。在创建 person
对象后,我们可以使用这个符号来调用 Person
类的方法。
well-known symbol
well-known symbol 是一组预定义的符号类型,用于定义对象的内部行为。这些符号包括 Symbol.iterator
、Symbol.toStringTag
、Symbol.toPrimitive
等等。
well-known symbol 的语法如下:
const mySymbol = Symbol.iterator;
在这个例子中,我们使用 Symbol.iterator
创建了一个 well-known symbol,用于定义对象的迭代器行为。
Symbol.iterator
Symbol.iterator
是 well-known symbol 中最常用的符号类型之一。它用于定义对象的迭代器行为,使得我们可以使用 for...of
循环或 Array.from
方法来遍历对象的元素。
例如,我们可以创建一个自定义的 Range
类,并使用 Symbol.iterator
来定义它的迭代器行为:
// javascriptcn.com 代码示例 class Range { constructor(start, end) { this.start = start; this.end = end; } *[Symbol.iterator]() { for (let i = this.start; i <= this.end; i++) { yield i; } } } const range = new Range(1, 5); for (let num of range) { console.log(num); // 输出:1 2 3 4 5 }
在这个例子中,我们使用 Symbol.iterator
定义了 Range
类的迭代器行为,使得我们可以使用 for...of
循环来遍历 Range
对象的元素。
Symbol.toStringTag
Symbol.toStringTag
是另一个常用的 well-known symbol,它用于定义对象的默认字符串描述。当我们使用 Object.prototype.toString
方法来转换对象为字符串时,它会自动调用对象的 Symbol.toStringTag
方法来生成字符串描述。
例如,我们可以创建一个自定义的 Point
类,并使用 Symbol.toStringTag
来定义它的字符串描述:
// javascriptcn.com 代码示例 class Point { constructor(x, y) { this.x = x; this.y = y; } get [Symbol.toStringTag]() { return 'Point'; } } const point = new Point(1, 2); console.log(point.toString()); // 输出:[object Point]
在这个例子中,我们使用 Symbol.toStringTag
定义了 Point
类的字符串描述,使得当我们使用 point.toString()
方法来转换 point
对象为字符串时,它会返回 [object Point]
。
Symbol.toPrimitive
Symbol.toPrimitive
是一个比较特殊的 well-known symbol,它用于定义对象的类型转换行为。当我们使用一些运算符或方法来对对象进行类型转换时,它会自动调用对象的 Symbol.toPrimitive
方法来执行转换。
例如,我们可以创建一个自定义的 Money
类,并使用 Symbol.toPrimitive
来定义它的类型转换行为:
// javascriptcn.com 代码示例 class Money { constructor(amount) { this.amount = amount; } [Symbol.toPrimitive](hint) { if (hint === 'number') { return this.amount; } else { return `$${this.amount.toFixed(2)}`; } } } const money = new Money(10.5); console.log(money + 5); // 输出:15.5 console.log(String(money)); // 输出:$10.50 console.log(Number(money)); // 输出:10.5
在这个例子中,我们使用 Symbol.toPrimitive
定义了 Money
类的类型转换行为,使得当我们对 money
对象进行类型转换时,它会根据转换的类型返回不同的值。
总结
ES8/ES2017 中的类型名称符号和 well-known symbol 提供了一种更加灵活和可定制的方式来定义对象的行为。通过使用这些符号,我们可以更好地控制对象的行为,提高代码的可读性和可维护性。在实际开发中,我们可以根据具体的需求选择不同的符号类型,以便更好地实现业务逻辑。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6562f21fd2f5e1655dcaf312