前言
Symbol 是 ECMAScript 2015 引入的全新的原始数据类型,用于表示独一无二的值。在 ECMAScript 2017 中,Symbol 对象有了更多的应用场景,本文将对 Symbol 对象进行详细的介绍和讲解,包含其在对象属性、迭代器和原生方法中的应用,以及实际案例的代码示例。
Symbol 对象的基本使用
在 ECMAScript 2015 中,我们可以通过 Symbol() 函数创建一个全局唯一的 Symbol 值。例如:
const foo = Symbol(); const bar = Symbol(); console.log(foo === bar); // false
从以上代码可以看出,每个使用 Symbol() 创建的 Symbol 值都是独一无二的,即使它们的名称相同。
在 ECMAScript 2017 中,还新增了一些预定义的 Symbol 值,这些 Symbol 值被称为“内置 Symbol 值”。这些值可以通过 Symbol 类型的属性访问,例如:
console.log(Symbol.iterator); // Symbol(Symbol.iterator) console.log(Symbol.toPrimitive); // Symbol(Symbol.toPrimitive) const symbol = Symbol.for("foo"); console.log(symbol); // Symbol(foo)
其中,Symbol.iterator 用于指定迭代器对象的方法,Symbol.toPrimitive 用于指定一个对象被转换为原始类型的方式。Symbol.for() 方法可以根据给定的字符串创建一个全局唯一的 Symbol 值。
Symbol 对象在对象属性中的应用
我们可以使用 Symbol 类型的值作为对象的属性名,从而创建一个独一无二的属性,如下所示:
const obj = { [Symbol("foo")]: "bar" }; console.log(Object.getOwnPropertySymbols(obj)); // [ Symbol(foo) ] console.log(obj[Symbol("foo")]); // undefined console.log(obj[Object.getOwnPropertySymbols(obj)[0]]); // bar console.log(Object.keys(obj)); // []
从以上代码可以看到,我们可以使用 Symbol 类型的值作为对象的属性名,并且这个属性不会出现在对象的 keys() 方法返回的数组中,也不会被 for...in 循环遍历到。这种使用方法在定义一些内部属性、私有属性等场景中非常有用。
Symbol 对象在迭代器中的应用
在 ECMAScript 2015 中,我们可以通过实现一个具有 next() 方法的迭代器对象来实现可迭代的对象。在 ECMAScript 2017 中,我们可以使用 Symbol.iterator 内置 Symbol 值来指定一个迭代器对象的方法,如下所示:
const arr = [1, 2, 3]; const iterator = arr[Symbol.iterator](); console.log(iterator.next()); // { value: 1, done: false } console.log(iterator.next()); // { value: 2, done: false } console.log(iterator.next()); // { value: 3, done: false } console.log(iterator.next()); // { value: undefined, done: true }
从以上代码可以看到,我们可以通过使用 Symbol.iterator 内置 Symbol 值来获取一个可迭代对象的迭代器对象。该迭代器对象具有 next() 方法,通过调用 next() 方法可以访问到可迭代对象的每一个元素。
Symbol 对象在原生方法中的应用
在 ECMAScript 2017 中,Symbol 对象被广泛应用在了一些原生方法中,如 Object.getOwnPropertySymbols()、Reflect.ownKeys() 和 Symbol.search 等方法,以及 String、RegExp、Array 等对象的原型方法中。
Object.getOwnPropertySymbols() 方法
Object.getOwnPropertySymbols() 方法用于获取一个对象所有的 Symbol 类型的属性名,例如:
const obj = { [Symbol("foo")]: "bar", [Symbol("baz")]: "qux" }; console.log(Object.getOwnPropertySymbols(obj)); // [ Symbol(foo), Symbol(baz) ]
Reflect.ownKeys() 方法
Reflect.ownKeys() 方法用于获取一个对象所有的属性名,包括 Symbol 类型的属性名和字符串类型的属性名,例如:
const obj = { [Symbol("foo")]: "bar", [Symbol("baz")]: "qux", name: "Tom", age: 18 }; console.log(Reflect.ownKeys(obj)); // [ Symbol(foo), Symbol(baz), 'name', 'age' ]
Symbol.search 方法
Symbol.search 方法是字符串的原型方法,用于返回一个字符串中符合条件的子串的索引位置,例如:
const str = "Hello world"; console.log(str.search(/l/)); // 2 console.log(str.search(/w/)); // 6 console.log(str.search(/x/)); // -1
从以上代码可以看到,Symbol.search() 方法被用于返回一个字符串中符合条件的子串的索引位置。
示例应用场景
下面,我们来看一个具体的实际场景,在一个对象数组中查找是否存在某一个对象,如果不存在则将其添加到数组中。代码如下所示:
-- -------------------- ---- ------- ----- --- - - - ----- ------ ---- -- -- - ----- -------- ---- -- - -- ----- --- - - ----- ------- ---- -- -- ----- ------ - -------------- --- ----- - ------ --- ---- - - -- - - ----------- ---- - -- ------------ --- -------- -- ---------- --- -------- - ----- - ----- ------ - - -- -------- - ----------- - ----- -------------- ---------------- ------ --- ---- ----- -- --- -------- ----- - ---- - ---------------- ------ ------- ------ -- --- --------- -
从以上代码可以看到,我们使用 Symbol 类型的值作为扩展属性,以确保该属性不会与其它属性名称冲突。
总结
本文对 ECMAScript 2017 中的 Symbol 对象进行了详细的介绍和讲解,包含了其在对象属性、迭代器和原生方法中的应用场景和使用方法。Symbol 对象作为一种全新的原始数据类型,可以帮助开发者更好地进行代码设计和开发。在实际开发中,需要根据具体情况灵活运用。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64cde9eab5eee0b5255dc748