Symbol 是 ES6 中新增的一种数据类型,其主要作用是用来表示一个独一无二的标识符,常用于对象属性的名称、迭代器方法等场景。ES10 中增加了一些新的 API,本文将详细介绍 Symbol 的用法和新特性。
Symbol 的基本用法
Symbol 类型的值是一种基本数据类型,使用 Symbol 函数创建。下面是几个基本的使用示例:
const sym1 = Symbol(); const sym2 = Symbol("foo"); console.log(sym1); // Symbol() console.log(sym2); // Symbol(foo) typeof sym1 // "symbol" typeof sym2 // "symbol"
Symbol 函数可以接受一个字符串作为参数,表示该 Symbol 的描述信息。为了方便调试和查看,可以将描述信息打印出来:
const sym = Symbol("description"); console.log(String(sym)); // "Symbol(description)" console.log(sym.toString()); // "Symbol(description)"
Symbol 作为属性名
在对象中使用 Symbol 作为属性名时,该属性会被视为一个私有属性,不会出现在 for...in、Object.keys()、JSON.stringify() 等操作中。这样可以更好地保护对象的属性,避免被意外修改或访问。
const obj = {}; const sym = Symbol(); obj[sym] = "secret value"; console.log(obj[sym]); // "secret value" console.log(JSON.stringify(obj)); // "{}" console.log(Object.keys(obj)); // []
在某些场景下,我们也可以使用 Symbol 作为一些特殊属性的名称,比如迭代器方法。下面是一个示例:
-- -------------------- ---- ------- ----- ------------- - ------------------ ---- - ---------- - ------ -------- - ---- - ------------------- - --- ------- - ----------- ------ - ----- -- -- - -- -------- -- --------- - ------ - ------ ---------- ----- ----- -- - ---- - ------ - ----- ---- -- - - -- - - ----- ----- - --- ---------------- --- --- ------ ------ -- ------ - -------------------- - -- - -- - -- - -- - -- -
在 RangeIterator 类中,将 Symbol.iterator 方法定义为迭代器方法,使得该类的实例可以使用 for...of 循环进行遍历。
新增的 Symbol 属性
ES10 中新增了一些新的 Symbol 静态属性,这些属性的主要作用是提供一些已有方法的默认实现,也可以用于查找与 Symbol 相关的信息。下面是这些属性的具体介绍:
Symbol.asyncIterator
Symbol.asyncIterator 是一个 Symbol 值,代表一个对象的默认异步迭代器方法。通过该属性,对象可以实现异步迭代功能。
-- -------------------- ---- ------- ----- --- - - -------------------- - ----- -- ----- -- ----- -- -- ----- ------------------------- - --- ------ ----- -- ----- - ----- --- --------------- -- ------------------- ------- ----- ------ - - -- ------ -- -- - --- ----- ------ ------ -- ---- - -------------------- - ----- -- -- - ---- - -- -- - ---- - -- -- - ---- -
在 obj 对象中,通过定义 Symbol.iterator 来实现同步迭代,定义 Symbol.asyncIterator 来实现异步迭代。
Symbol.hasInstance
Symbol.hasInstance 也是一个 Symbol 值,用于派生类的继承,可以用来自定义 instanceof 运算符的行为。
class MyArray extends Array { static [Symbol.hasInstance](instance) { return Array.isArray(instance); } } const arr = []; console.log(arr instanceof MyArray); // true
在 MyArray 类中,使用 static 关键字定义了一个 Symbol.hasInstance 函数,该函数表示如果 instance 是数组的话,那么 arr 实例也是 MyArray 类的实例。
Symbol.matchAll
Symbol.matchAll 也是一个 Symbol 值,用于扩展字符串的 matchAll() 方法,返回一个正则表达式在字符串中所有匹配结果的迭代器。
const str = "Hello, world!"; const regexp = /[\s,]+/g; const matches = str.matchAll(regexp); for (const match of matches) { console.log(match); } // [" ", index: 5, input: "Hello, world!", length: 1]
Symbol.replace
Symbol.replace 是一个 Symbol 值,用于扩展字符串的 replace() 方法,用于实现自定义的替换逻辑。
-- -------------------- ---- ------- -------------------------------- - --------------------- ------------- - --- ------ - --- --- ---------- - -- --- ---------- - ------------------------- ------------ ----- ----------- --- --- - ------ -- ---------------------- ----------- - ------------- ---------- - ---------- - ------------------- ---------- - ------------------------- ------------ - ------ -- ----------------------- ------ ------- -- ----- --- - ------- -------- ---------------------------- ------ -- ------- -------
在该示例中,通过将 [Symbol.replace] 属性赋值为一个自定义的函数,重写了字符串的替换逻辑。
Symbol.search
Symbol.search 是一个 Symbol 值,用于扩展字符串的 search() 方法,用于实现自定义的匹配逻辑。
String.prototype[Symbol.search] = function(searchValue) { const index = this.indexOf(searchValue); return index === -1 ? -1 : 2 * index; }; const str = "Hello, world!"; console.log(str.search(",")); // 12
总结
本文介绍了 Symbol 的基本用法和新增的特性,包括使用 Symbol 作为属性名、Symbol 迭代器方法、Symbol 静态属性等内容。Symbol 的特性使得我们可以更好地保护对象的私有属性,同时也可以扩展已有方法的实现,更好地适应代码的需求。希望本文对读者有所帮助,对学习 ES10 及前端开发有所指导。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/653d02a67d4982a6eb6ece4e