开启掘金成长之旅!这是我参与「掘金日新计划 · 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
运行结果:
通过运行结果可以发现,相同参数 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
运行结果:
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("---循环结束---");
循环后可以观察到没有任何输出:
Symbol 不会被读取到的操作:
- for...in 循环
- for...of 循环
- Object.keys()
- Object.getOwnPropertyNames()
Symbol 可以被读取到的操作:
- Object.getOwnPropertySymbols()
- Reflect.ownKeys()
深拷贝和 Symbol
另外,深拷贝的解决方案之一是 Json.parse(Json.stringfy(obj)),它的缺点除了无法处理循环引用之外,还会忽略一些数据类型,Symbol 就是其中之一(undefined Symbol function 都会被忽略)