ECMAScript 2019 中关于 Symbol 的新概念与用法讲解

阅读时长 8 分钟读完

在 ECMAScript 2015 中,我们认识了一种新的基本数据类型 Symbol(符号) 。在 ECMAScript 2019 中,Symbol 得到了更多的新概念、新特性以及更广泛的应用场景。本文主要介绍 ECMAScript 2019 中关于 Symbol 的新概念与用法,旨在帮助前端开发者更好地理解 Symbol,掌握它的使用方法,提高开发效率和代码质量。

Symbol 的定义和基本用法

Symbol 是 ECMAScript 6 中引入的一种新的基本数据类型,表示一个独一无二的值。它通过 Symbol() 函数创建一个独一无二的值,在使用时可以通过变量名来访问。

在上面的代码中,我们创建了两个 Symbol 类型的变量 sym1 和 sym2,由于每个 Symbol 的值都是独一无二的,因此两个变量的值也不相等。使用 Symbol() 函数创建的值是不能通过文字或表达式来创建的,只能通过函数来创建。

Symbol 的新概念

在 ECMAScript 2019 中,Symbol 得到了更多的新概念,包括如下几种。

Symbol.hasInstance

Symbol.hasInstance 属性是一个函数,用来判断一个对象是否为另一个对象的实例。

在上面的代码中,我们创建了一个类 Foo,并定义了 Symbol.hasInstance 属性,通过该属性让 JavaScript 引擎在检查 obj instanceof Foo 时使用该函数进行判断。由于 [] 是一个数组,因此它是 Foo 的一个实例,而 obj 不是一个数组,因此它不是 Foo 的实例。

Symbol.asyncIterator

Symbol.asyncIterator 属性是一个函数,表示一个异步迭代器接口,用于定义异步遍历的行为。

-- -------------------- ---- -------
----- --- - --- -- ---

----- -------- ------ -
  --- ----- ------ ----- -- ---- -
    -------------------
  -
-

-------

在上面的代码中,我们通过 for await...of 循环遍历一个数组,并使用 Symbol.asyncIterator 属性来表示该数组是一个异步迭代器。

Symbol.match

Symbol.match 属性是一个函数,用于确定一个对象是否具有正则表达式的匹配能力。

在上面的代码中,我们创建了一个类 Foo,并定义了 Symbol.match 属性,通过该属性让 JavaScript 引擎在进行正则表达式匹配时使用该函数进行判断。由于 "foobar" 中包含 "foo",因此它符合 Foo 的匹配规则,而 "bar" 不包含 "foo",因此不符合匹配规则。

Symbol.replace

Symbol.replace 属性与 Symbol.match 属性相对应,用于将一个字符串中符合某种条件的文本替换成另一个文本。

在上面的代码中,我们创建了一个类 Foo,并定义了 Symbol.replace 属性,通过该属性让 JavaScript 引擎在进行字符串替换时使用该函数进行判断。由于 "foobar" 中包含 "foo",因此它符合 Foo 的替换规则,替换成了 "hello",最终输出 "helloBar"。

Symbol.search

Symbol.search 属性用于确定一个对象是否可以被用作字符串匹配的目标。

在上面的代码中,我们创建了一个类 Foo,并定义了 Symbol.search 属性,通过该属性让 JavaScript 引擎在进行字符串搜索时使用该函数进行判断。由于 "foobar" 中包含 "foo",因此它符合 Foo 的匹配规则,搜索到了 "foo" 的位置 0,而 "bar" 不包含 "foo",因此没有搜索到。

Symbol.species

Symbol.species 属性是一个函数,用于创建导致派生对象的默认构造函数。它在 Array.prototype.map()、Array.prototype.filter()、Array.prototype.slice() 等方法里应用非常广泛。通过 Symbol.species 属性,我们可以指定一个函数,用于在方法调用时创建一个新的派生对象。

-- -------------------- ---- -------
----- ------- ------- ----- -
  ------ --- ------------------ -
    ------ ------
  -
-

----- ------- - --- ---------- -- ---

----- -------- - ----------------- -- ----- - ---
-------------------- ---------- --------- -- -----
-------------------- ---------- ------- -- ----

在上面的代码中,我们创建了一个 MyArray 类,继承了 Array 类,并定义了 Symbol.species 属性。Map 方法在对输出值类型的计算时,将使用这个符号属性来决定返回值的类型。而在MyArray 类中,我们通过 Symbol.species 属性指定了 Array 构造函数,因此 map 的返回值为一个新的 Array 对象。

Symbol 的应用场景

Symbol 的应用非常广泛,可以用于对象属性名、私有属性(使用 Symbol 的结果会使这个变量更像私有变量)、类方法及原型方法的定义等多个方面。下面列举一些常见的应用场景。

防止属性名冲突

在 JavaScript 中,对象的属性名都是字符串。如果多个对象的属性名相同,可能会导致冲突。而使用 Symbol,则可以保证属性名不会重复。

自定义迭代器

使用 Symbol.iterator 属性可以自定义迭代器。

-- -------------------- ---- -------
----- ---------- - -
  ------------------- -
    --- - - --
    ------ -
      ------ -
        -- -- - -- -
          ------ -
            ------ ----
            ----- -----
          --
        - ---- -
          ------ -
            ------ ----------
            ----- ----
          --
        -
      -
    --
  -
--

--- ------ ----- -- ----------- -
  -------------------
-

在上面的代码中,我们定义了一个 myIterable 对象,并在该对象上添加 Symbol.iterator 属性,表示该对象可以被迭代。使用 for...of 循环遍历该对象时,会逐个输出该对象的值。

私有属性实现

使用 Symbol 可以实现类似于私有属性的功能,因为使用 Symbol 的结果会使这个变量更像私有变量,无法被直接访问。

-- -------------------- ---- -------
----- ---- - ---------------

----- ------ -
  ------------- -
    ---------- - ------
  -
  --------- -
    ------ -----------
  -
-

----- ------ - --- ---------
------------------------------ -- ---
------------------------- -- ---------

在上面的代码中,我们通过 Symbol 键定义了一个私有属性,只能通过类中的方法来访问。

总结

在 ECMAScript 2019 中,Symbol 收到了更广泛的应用,如 Symbol.hasInstance、Symbol.asyncIterator、Symbol.match 等等。通过本文的讲解,了解了 Symbol 的新概念、用法和应用场景,相信对前端开发者来说都是非常有意义的。在实际开发中,合理使用 Symbol,可以帮助我们提高代码的可读性和可维护性。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64fe6bd095b1f8cacdd3225d

纠错
反馈