持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第13天,点击查看活动详情
ES6新增了一种数据类型--symbol(符号类型)。
Symbol是什么
Symbol是一种原始数据类型,并且是在ES6才新增的,它是唯一的、不可变的。
创建Symbol
创建Symbol是用Symbol()函数初始化。并且不能使用new关键字一起使用。
let sym = Symbol();
console.log(typeof sym);//symbol
let sym2 = new Symbol(); // Uncaught TypeError: Symbol is not a constructor
还可以给Symbol()函数传递字符串参数作为符号的描述。但是,这个符号的参数与符号定义或者标识完全无关。并且,符号是唯一的。
let s1 = Symbol('a');
let s2 = Symbol('a');
console.log(s1 === s2); //false
console.log(s1); // Symbol('a')
console.log(s2); // Symbol('a')
从上面我们可以看出,Symbol()函数不是一个构造函数,应该是一个工厂函数,调用这个函数后,就会return一个符号。
description
每一个符号都有一个属性description,它会返回该符号的描述
let sym = Symbol('ly');
console.log(sym.description); // 'ly'
使用全局符号注册表
Symbol.for()对每一个字符串键(就是用一个字符串作为健,并且参数里面的任何值都会被转成String类型)都执行幂等操作。
幂等操作:多次操作的结果与一次操作的结果相同。
Symbol.for()第一次使用某个字符串调用时,它会检查全局运行时注册表,发现不存在对应的符号,于是就会生成一个新符号实例并添加到注册表中。后续使用相同字符串的调用同样会检查注册表,发现存在与该字符串对应的符号,然后就会返回该符号实例。
let s1 = Symbol.for('ll');
let s2 = Symbol.for('ll');
console.log(s1 === s2); //true
let s3 = Symbol.for('lly');
console.log(s1 === s3); //false
但是只有都使用Symbol.for()且参数相同定义的符号才会相同,如果一个使用Symbol.for(),一个使用Symbol(),哪怕参数相同也不会相同。(虽然都是符号,但是Symbol.for()是存放在符号注册表中的)
let s1 = Symbol.for('ly');
let s2 = Symbol('ly');
console.log('s1 === s2'); //false
Symbol.keyFor()
可以使用Symbol.keyFor()来查询全局符号注册表,接收符号为参数,返回该符号的字符串键。
let s1 = Symbol.for('ly');
console.log(Symbol.keyFor(s1)); // ly
该方法只对全局符号注册表有用,如果是普通符号:
let s1 = Symbol('ly');
console.log(Symbol.keyFor(s1)); //undefined
如果是其他类型的值:
let a = 10;
console.log(Symbol.keyFor(a));// TypeError: 10 is not a symbol
Symbol的作用
那么这个Symbol的作用是啥呢?
------》 因为Symbol是唯一的嘛,我们常常使用Symbol来创建唯一的记号,进而用来作非字符串形式的对象属性。
假如一个班上有两个同学的名字是一样的,都叫张三,而现在我们需要统计这个班上每一个同学的期末成绩,那么如果使用对象来存储的话,属性名相同的属性就会被后面的替换掉。
let obj1 = {
name:'张三'
}
let obj2 = {
name:'张三'
}
let grade = {
[obj1.name]:{
math:95,
english:89
},
[obj2.name]:{
math:87,
english:98
}
}
console.log(grade);
// {张三: {…}}
- 张三: {math: 87, english: 98}
- Prototype]]: Object
我们发现grade对象中只有后面个张三的属性,前一个被替换掉了。再简单看一下:
let obj = {
zhangsan:10,
zhangsan:22
}
console.log(obj) //{zhangsan: 22}
这个时候我们就可以使用Symbol了。
let obj = {
[Symbol('zs')]:10,
[Symbol('zs')]:22
}
console.log(obj);
// {Symbol(zs): 10, Symbol(zs): 22}
console.log(obj[Symbol('zs')]); //undefined
但是这样我们就不能取出这个值了,所以一般我们会用一个变量来接收这个值。因为console.log(obj[Symbol('zs')]);里面的Symbol('zs')又是一个新的唯一的符号了。
let obj1 = {
name:'张三',
key:Symbol('张三')
}
let obj2 = {
name:'张三',
key:Symbol('张三')
}
let grade = {
[obj1.key]:{
math:95,
english:89
},
[obj2.key]:{
math:87,
english:98
}
}
console.log(grade);
同时还可以取出来。
.....接上面的代码....
console.log(grade);
console.log(grade[obj1.key]); // {math: 95, english: 89}
console.log(grade[obj2.key]); // {math: 87, english: 98}
此外,使用Symbol符号作为对象的属性名,该属性名是属于被保护的,也就是不能使用key..in 和 key..of访问得到。
let sym = Symbol();
let obj = {
[sym]:'符号',
name:'ly',
sayName() {
console.log(this.name)
}
}
for(let key in obj) {
console.log(key)
}
// name
// sayName
可以使用 Object.getOwnPropertySymbols() 方法得到对象的符号属性,但是不能得到普通属性。
let sym = Symbol();
let obj = {
[sym]:'符号',
name:'ly',
sayName() {
console.log(this.name)
}
}
console.log(Object.getOwnPropertySymbols(obj)); // [Symbol()]