1. Symbol是什么
ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,前六种是:undefined、null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。
Symbol的作用非常的专一,换句话说其设计出来就只有一个目的——作为对象属性的唯一标识符,防止对象属性冲突发生。
举个例子,产品组来了一个妹子,我们想了解她的更多信息,就询问hr、产品的同事,得到下面这样的信息:
let info1 = {
name: '静静',
age: 24,
job: '产品经理',
description: '平时喜欢做做瑜伽,人家有男朋友,你别指望了'
}
let info2 = {
description: '这小姑娘挺好的,挺热情的,嘿嘿嘿……'
}
Object.assign(info1, info2)
//结果如下
{
name: '静静',
age: 24,
job: '产品经理',
description: '这小姑娘挺好的,挺热情的,嘿嘿嘿……'
}
注意:_Object.assign()_方法用于将所有可枚举属性的值从一个或多个源对象source复制到目标对象。它将返回目标对象target。第一个参数是目标对象,后面的参数都是源对象。如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。
Object.assign()方法实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。
对这两个数据进行汇总,结果发现,描述都用了同一个对象属性description,于是整合的时候,就容器冲突,覆盖,导致“人家有男朋友”这么重要的信息都没注意到。如果用Symbol就没有这样的烦恼了。
let info1 = {
name: '静静',
age: 24,
job: '产品经理',
[Symbol('description')]: '平时喜欢做做瑜伽,人家有男朋友,你别指望了'
}
let info2 = {
[Symbol('description')]: '这小姑娘挺好的,挺热情的,嘿嘿嘿……'
}
Object.assign(info1, info2)
//结果如下
{
age: 24
job: "产品经理"
name: "静静"
Symbol(description): "平时喜欢做做瑜伽,人家有男朋友,你别指望了"
Symbol(description): "这小姑娘挺好的,挺热情的,嘿嘿嘿……"
}
2. Symbol的语法
Symbol([description])
其中description为可选参数,字符串,没什么特别的作用,就是debug调试的时候可以用来作为标记。
let s = Symbol();
typeof s // "symbol" 表明变量s是 Symbol 数据类型
let s2 = Symbol('foo');
let s3 = Symbol('foo');
s2 === s3 // false
3. Symbol.for()
如果想重新使用同一个 Symbol 值,Symbol.for()方法可以做到这一点。它接受一个字符串作为参数,然后搜索有没有以该参数作为名称的 Symbol 值。如果有,就返回这个 Symbol 值,否则就新建一个以该字符串为名称的 Symbol 值,并将其注册到全局。
let s1 = Symbol.for('foo');
let s2 = Symbol.for('foo');
s1 === s2 // true
//s1和s2都是 Symbol 值,但是它们都是由同样参数的Symbol.for方法生成的,所以实际上是同一个值。
Symbol.for()为 Symbol 值登记的名字,是全局环境的,不管有没有在全局环境运行。
function foo() {
return Symbol.for('bar');
}
const x = foo();
const y = Symbol.for('bar');
console.log(x === y); // true
上面代码中,Symbol.for('bar')是函数内部运行的,但是生成的 Symbol 值是登记在全局环境的。所以,第二次运行Symbol.for('bar')可以取到这个 Symbol 值。
Symbol.for()与Symbol()的区别
Symbol.for()与Symbol()这两种写法,都会生成新的 Symbol。它们的区别是,前者会被登记在全局环境中供搜索,后者不会。Symbol.for()不会每次调用就返回一个新的 Symbol 类型的值,而是会先检查给定的key是否已经存在,如果不存在才会新建一个值。比如,如果你调用Symbol.for("cat")30 次,每次都会返回同一个 Symbol 值,但是调用Symbol("cat")30 次,会返回 30 个不同的 Symbol 值。
4. Symbol.keyFor()
Symbol.keyFor()方法返回一个已登记的 Symbol 类型值的key。
let s1 = Symbol.for("foo");
Symbol.keyFor(s1) // "foo"
let s2 = Symbol("foo");
Symbol.keyFor(s2) // undefined 变量s2属于未登记的 Symbol 值,所以返回undefined