在 ES6 中使用新的数据类型 Symbol

在ECMAScript 6(简称 ES6)中,引入了一个新的数据类型——Symbol。Symbol 类型是一种原始数据类型,在 JavaScript 中只有它自己和另外五种(undefined、null、boolean、string、number)数据类型一样。Symbol 类型的值是唯一的和不可改变的,可以认为是一种标志。在本文中,我们将详细介绍 Symbol 类型,包括创建 Symbol 类型的几种方式、Symbol 值的作用与用法以及一些实际应用的示例。

创建 Symbol 类型

要创建 Symbol 值,我们可以使用全局函数 Symbol()

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

Symbol() 函数接受一个可选的字符串参数,用于指定 Symbol 的描述,主要用于 Symbol 的调试。例如:

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

我们可以看到,两个相同描述的 Symbol 值不相等,描述不同的 Symbol 值才相等。

除了 Symbol() 函数,还有几种用于创建 Symbol 的方式,如下:

  • Symbol.for(key):该方法接受一个字符串参数,用于在全局 Symbol 注册表中查找或创建一个 Symbol 值。如果找到则返回该 Symbol 值,否则创建新的 Symbol 值并在全局 Symbol 注册表中注册,然后返回该 Symbol 值。例如:

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

    在该示例中,我们创建了两个描述相同的 Symbol 值,发现它们是相等的。这是因为我们使用了 Symbol.for() 方法并传入相同的参数。这样创建出来的 Symbol 值会在全局注册表中进行查找,如果找到了就返回已有的,否则创建新的并注册之后返回。

  • Symbol.iterator:该方法返回对象默认可迭代的迭代器。我们可以用这个方法来自定义对象的迭代器。例如:

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

    在该示例中,我们使用 arr[Symbol.iterator]() 方法返回 arr 的默认迭代器,然后使用 iter.next() 方法来获取迭代器中的每个值。当迭代器遍历完所有值后,done 属性值为 truevalue 属性值为 undefined

Symbol 值的作用与用法

在 ES6 中,Symbol 类型的值主要有三个用途:

  • 对象属性名的唯一性

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

    在上面的例子中,我们使用了一个 Symbol 值作为 obj 对象属性名。由于 Symbol 的值是唯一的,我们可以确保该属性名不会冲突,即便 obj 对象中同时存在相同变量名属性。这也是 Symbol 类型存在的原初意义:解决属性命名冲突问题。

  • 私有属性的模拟

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

    在上面的代码中,我们模拟了一个私有属性。使用 Symbol 值作为私有属性的名称,避免了被改写的风险,同时保证了私有属性访问的安全和灵活性。在该示例中,通过把 _age 作为 Symbol 值赋予对象来模拟私有属性,getset 方法让我们能够像使用普通属性一样来访问和修改私有属性。

  • 枚举值遍历

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

    在该示例中,我们将多个不同的 Symbol 值放到了一个数组中,在遍历时,我们可以使用 for…of 循环进行遍历。因为 Symbol 类型的值是不可被枚举的,所以我们可以在 for…of 循环中正确地遍历整个数组。

示例代码

我们再来看两个更具体的示例代码,更展示 Symbol 类型的实际应用。

  • 实现唯一标识符

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

    在该示例中,我们创建了一个 uuid() 函数,该函数使用 Symbol 值作为返回值,同时 Symbol 值的描述使用了一种随机算法来生成唯一标识符,确保每次调用 uuid() 函数都可以获得一个唯一的标识符。该方法类似于通常用于生成 GUID 的方式。该方法生成出来的 Symbol 值既有唯一性,也有较高的随机性。

  • 实现对对象成员的封装

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

    在该示例中,我们使用了 _name_age 的 Symbol 值作为私有属性,以便我们可以封装对象属性。由于 Symbol 类型的全局唯一性,它可以和普通字符串属性名作为相同等价,放到对象内作为属性。get [Symbol.toStringTag] 方法允许我们对对象的字符串表示形式进行自定义。例如,在终端中输出 console.log(p) 得到结果为:

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

    这里 Symbol(name)Symbol(age) 成功封装了私有属性,不会显式输出。

结论

Symbol 类型是 JavaScript 语言中的一种新的数据类型,其作为一种原始数据类型,具有不可变性和唯一性,可用于处理特定领域的问题——如定义对象的属性名、枚举值遍历、实现松散耦合等。在实际应用中,我们可以采用以上几种方式创建和应用 Symbol 类型,更可发挥出它的功效来。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6735a1b10bc820c5824f94a2