ES9 中新增了两个 Symbol,分别是 Symbol.species 和 Symbol.matchAll。这两个 Symbol 可以帮助我们更好地处理一些常见的问题,同时也可以提高代码的可读性和可维护性。
Symbol.species
Symbol.species 是一个构造函数的属性,它用来指定一个衍生对象应该使用的构造函数。在一些情况下,我们需要创建一个新的对象,但是又需要保留原始对象的类型信息。这时候就可以使用 Symbol.species。
举个例子,假设我们有一个 Vector 类,它用来表示一个二维向量:
// javascriptcn.com 代码示例 class Vector { constructor(x, y) { this.x = x; this.y = y; } get length() { return Math.sqrt(this.x * this.x + this.y * this.y); } static add(v1, v2) { return new Vector(v1.x + v2.x, v1.y + v2.y); } }
现在我们想要实现一个 Vector 的衍生类,用来表示一个三维向量。我们可以这样写:
// javascriptcn.com 代码示例 class Vector3D extends Vector { constructor(x, y, z) { super(x, y); this.z = z; } get length() { return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); } }
这样做没问题,但是有一个潜在的问题:如果我们调用 Vector3D.add(v1, v2) 方法,它返回的将是一个 Vector 对象,而不是 Vector3D 对象。这是因为 add 方法中使用了 new Vector,而不是 new this.constructor。我们可以改成这样:
class Vector { // ... static add(v1, v2) { const Constructor = v1.constructor[Symbol.species] || v1.constructor; return new Constructor(v1.x + v2.x, v1.y + v2.y); } }
现在,如果我们调用 Vector3D.add(v1, v2) 方法,它将返回一个 Vector3D 对象,而不是 Vector 对象。
Symbol.matchAll
Symbol.matchAll 是一个全局的 Symbol,它用来指定一个正则表达式应该返回所有匹配结果,而不仅仅是第一个。
举个例子,假设我们有一个字符串,里面包含多个 URL:
const str = 'Visit my website at https://example.com/ and also https://google.com/';
现在我们想要提取出所有的 URL。我们可以使用正则表达式 /https?://\S+/g:
const regex = /https?:\/\/\S+/g; const matches = str.match(regex); console.log(matches); // ['https://example.com/', 'https://google.com/']
这样做没问题,但是如果我们想要知道每个 URL 在字符串中的位置,就需要使用 exec 方法:
let match; while ((match = regex.exec(str))) { console.log(match[0], match.index); }
这样做也没问题,但是如果我们想要一次性提取出所有的匹配结果,并且包含每个匹配结果在字符串中的位置,就可以使用 Symbol.matchAll:
// javascriptcn.com 代码示例 const regex = /https?:\/\/\S+/g; const matches = Array.from(str.matchAll(regex), match => ({ url: match[0], index: match.index, })); console.log(matches); // [ // { url: 'https://example.com/', index: 19 }, // { url: 'https://google.com/', index: 42 } // ]
这样做可以大大简化代码,同时也可以提高代码的可读性和可维护性。
总结
ES9 中的 Symbol.species 和 Symbol.matchAll 可以帮助我们更好地处理一些常见的问题,同时也可以提高代码的可读性和可维护性。在使用它们的时候,我们需要注意它们的语法和用法,以及它们的适用场景。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/6506920195b1f8cacd25e421