Symbol是什么?
Symbol是ES6中新增的一个基本数据类型,翻译为符号。
为什么需要Symbol呢?
在ES6之前,对象的属性名都是字符串形式,那么很容易造成属性名的冲突。比如原来有一个对象,我们希望在其中添加一个新的属性和值,但是我们在不确定它原来内部有什么内容的情况下, 很容易造成冲突,从而覆盖掉它内部的某个属性,比如开发中我们使用混入,那么混入中出现了同名的属性,必然有一个会被覆盖掉。
Symbol就是为了解决上面的问题,用来生成一个独一无二的值。
- Symbol值是通过Symbol函数来生成的,生成后可以作为属性名
- 也就是在ES6中,对象的属性名可以使用字符串,也可以使用Symbol值
- Symbol即使多次创建值,它们也是不同的:Symbol函数执行后每次创建出来的值都是独一无二的
- 我们也可以在创建Symbol值的时候传入一个描述description:这个是ES2019(ES10)新增的特性
代码案例
//ES6之前,对象的属性名(key)
const obj = {
name:'why',
friend:{name:"kobe"},
"age":18
}
console.log(obj); //{ name: 'why', friend: { name: 'kobe' }, age: 18 }
console.log(Object.keys(obj)); //[ 'name', 'friend', 'age' ]
//底层都是当成字符串的
// 字符串都是不能重复的(key)的名词
//比如
obj['name'] = 'james'; //覆盖了原来的name
console.log(obj); //{ name: 'james', friend: { name: 'kobe' }, age: 18 }
//为了避免产生冲突,es6新增了一种数据类型Symbol,它可以生独一无二的值。
//ES6中的Symbol
const s1 = Symbol()
const s2 = Symbol()
console.log(s1 === s2); //false
//ES2019(ES10),Symbol还有一个描述
const s3 = Symbol("这是Symbols3")
console.log(s3.description); //这是Symbols3
//3.Symbol值作为key
//3.1写法1,在定义对象字面量时使用
const objS = {
[s1]:'abc',
[s2]:'cba'
}
//3.2新增属性
objS[s3] = "nba"
const s4 = Symbol()
//3.3 Object.defineProperty方式
Object.defineProperty(objS,s4,{
enumerable:true,
value:"mba"
})
console.log(objS[s1],objS[s2],objS[s3],objS[s4]); //abc cba nba mba
//注意,不能通过.语法来获取Symbol
console.log(obj.s1); //undefined
//4.使用Symbol作为Key的属性名,在遍历/Object.keys的情况下都是获取不到Symbol值的
console.log(Object.keys(objS)); //[]
console.log(Object.getOwnPropertyNames(objS)); //[],这样也是空
//需要通过Object.getOwnPeoperySymbols来获取所有Symbol的key
console.log(Object.getOwnPropertySymbols(objS)); //[ Symbol(), Symbol(), Symbol(这是Symbols3), Symbol() ]
//有些时候我们希望Symbol是一样的
//这就需要用到Symbol.for(key)了
const sa = Symbol.for("aaa")
const sb = Symbol.for("aaa")
console.log(sa === sb); //true
//获取key
const key = Symbol.keyFor(sa)
console.log(key); //aaa
const sc = Symbol.for(key)
console.log(sa === sc); //true