JS | 关于 Symbol 需要了解这些内容

92 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第18天,点击查看活动详情

Symbol 是 ES6 新引入的一种新的数据类型,表示独一无二的值。在 ES5 中,对象属性名是字符串类型,可能会导致属性名称的冲突。

在面试题中 Symbol 也是出现频率很高的知识点。

先来回忆一下 JS 中的 7 种数据类型:

  • 基本数据类型(6 种)
    • 数值(Number)
    • 字符串(String)
    • 布尔(Boolean)
    • undefined
    • null
    • Symbol
  • 引用数据类型(1 种)
    • 对象(Object)

Symbol 语法

Symbol 类型的值通过 Symbol 函数生成,没有 new 字符,参数为字符串

如下代码就是对于 Symbol 的基本操作:

let s = Symbol("test");
console.log(s);
typeof(s); // "symbol 类型"

let s1 = Symbol("test");
console.log(s === s1); // false

运行结果:

image.png

通过运行结果可以发现,相同参数 Symbol() 返回的值不相等,所以可以保持字段的唯一性。

Symbol.for()

全局查找已登记的 Symbol 中是否有该字符串参数作为名称的 Symbol 值。

  • 如果有:返回这个 Symbol 值
  • 如果没有:新建并返回 Symbol 值
let test = Symbol("test");
let test1 = Symbol.for("test");
console.log(test === test1);      // false

let test2 = Symbol.for("test");
console.log(test1 === test2);     // true

运行结果:

image.png

Symbol.keyFor()

检测该字符串参数作为名称的 Symbol 值是否已被登记

遍历 和 Symbol

for...in 语句遍历一个对象种除了 Symbol 类型之外的的属性(不遍历可枚举属性)

let testSymbol = Symbol("testSymbol");
let myObject = {};
myObject[testSymbol] = "test";
console.log('myObject:',myObject);

console.log("---循环开始---");
for (let i in myObject) {
    console.log(i);
}    // 无输出
console.log("---循环结束---");

循环后可以观察到没有任何输出:

image.png

Symbol 不会被读取到的操作:

  • for...in 循环
  • for...of 循环
  • Object.keys()
  • Object.getOwnPropertyNames()

Symbol 可以被读取到的操作:

  • Object.getOwnPropertySymbols()
  • Reflect.ownKeys()

深拷贝和 Symbol

另外,深拷贝的解决方案之一是 Json.parse(Json.stringfy(obj)),它的缺点除了无法处理循环引用之外,还会忽略一些数据类型,Symbol 就是其中之一(undefined Symbol function 都会被忽略)