1、概述
ES5的对象属性名都是字符串,这容易造成属性名的冲突。比如,你使用了一个他人提供的对象,但又想为这个对象添加新的方法(mixin模式),新方法的名字就有可能与现有方法产生冲突。如果有一种机制,保证每个属性的名字都是独一无二的就好了,这样就从根本上防止属性名的冲突。这就是ES6引入Symbol的原因。
symbol是一种新的数据类型
数据类型
基本类型:Number、String、Boolean、undefined、null
引用类型:Object、Array、Function、Date等等
Symbol的特性就是唯一性
Symbol(符号)是一种新的基本类型值
2、基本使用
let a = Symbol()
let b = Symbol("hello")
console.log(a)
console.log(b)
}
3、Symbol的唯一性
Symbol是代表唯一的意思,同值的Symbol是不相等的
let a = Symbol()
let b = Symbol()
let c = Symbol("hello")
let d = Symbol("hello")
console.log(a == b)//false
console.log(c == d)//false
即使内部传入参数相同也不相等
4、Symbol的内部参数
4.1Symbol内部如果是字符串表示当前这个符合的描述信息
let b = Symbol("hello")
4.2 Symbol内部如果是对象,并且有toString方法,返回的就是这个符号的描述
let a = Symbol({
a:100,
toString:function () {
return "symbol 的描述信息"
}
})
console.log(a)
//返回--------------Symbol(symbol 的描述信息)
4.3 Symbol内部如果是数组,内部的参数会被扁平化,用逗号隔开
let a = Symbol([
1,2,3,'a','v','c'
])
console.log(a)
/返回------------Symbol(1,2,3,a,v,c)
5、Symbol的应用场景
用Symbol来创建对象的内部属性,内部属性的特点是防止外部获取或者随意篡改
let sym = Symbol("objKey")
let obj = {
a:100,
b:200,
c:300,
[sym]:666
}
obj.c = 888;
console.log(obj)
console.log(obj[Symbol("objKey")])
symbol定义的属性,外部是无法获取的,因为symbol同值是不相等的。即:symbol("objKey") != symbol("objKey")
对象遍历symbol的时候是得不到这个key
let sym = Symbol("objKey")
let obj = {
a:100,
b:200,
c:300,
[sym]:666
}
obj.c = 888;
for(let item in obj){
console.log(item)
}
Object.keys方法也不能获取symbol对应的key
console.log(Object.keys(obj))
6、获取对象中Symbol的key的方法
6.1 Object.getOwnPropertySymbols(obj)
Object.getOwnPropertySymbols,返回的是只有symbol定义的key
let sym = Symbol("objKey")
let obj = {
a:100,
b:200,
c:300,
[sym]:666
}
console.log(Object.getOwnPropertySymbols(obj))
6.2 Reflect.ownKeys(obj)
Reflect.ownKeys,返回的是所有的key,包含symbol定义的key
let sym = Symbol("objKey")
let obj = {
a:100,
b:200,
c:300,
[sym]:666
}
console.log(Reflect.ownKeys(obj))
获取对象中symbol对应的值
let sym = Symbol("objKey")
let obj = {
a:100,
b:200,
c:300,
[sym]:666
}
let num = obj[Object.getOwnPropertySymbols(obj)[0]];
console.log(num) ///666
7、共享符号
普通符号
let a = Symbol()
共享符号
let a = Symbol.for()
.for()就代表创建了一个共享的符号,内部参数也是描述信息
let symFor = Symbol.for("Symbol");
let symFor2 = Symbol.for("Symbol");
console.log(symFor == symFor2) ///true
上面的结果返回的是true,机理是:Symbol.for()定义的符号代表共享符号,如果创建了共享符号,此时就相当于在 全局创建了一个符号,此时如果再次创建相同描述的符号,就不会再创建新的了,而是将原来的抛出,所以结果是相等的
Symbol.keyFor()
Symbol.keyFor()方法来获取已经注册到全局的共享符号的描述信息
let symFor = Symbol.for("Symbol");
let symFor2 = Symbol.for("Symbol");
console.log(Symbol.keyFor(symFor))
///Symbol
8、Symbol的注意事项
8.1 Symbol值不能与其他类型的值进行运算,会报错
var sym = Symbol('My symbol');
"your symbol is " + sym // 报错Cannot convert a Symbol value to a string
8.2 Symbol值可以显式转为字符串
var sym = Symbol('My symbol');
String(sym) // 'Symbol(My symbol)'
sym.toString() // 'Symbol(My symbol)'
8.3、Symbol值也可以转为布尔值,但是不能转为数值
var sym = Symbol();
Boolean(sym) // true
Number(sym) // TypeError
sym + 2 // TypeError