Symbol 独一无二的值,一种新的原始数据类型,类似于一种特殊字符串。
声明
声明时可传入描述值,通过description读取描述值
- 声明方式一,Symbol(...)
slet s1 = Symbol();
let s2 = Symbol();
console.log(s1); //Symbol()
console.log(s2); //Symbol()
console.log(s1 === s2); //false ,返回的字符串一样但是不相等
//声明时传入字符串,就能知道当前是哪一个Symbol
let s3 = Symbol('foo');
let s4 = Symbol('bar');
console.log(s3); //Symbol(foo)
console.log(s4); //Symbol(bar)
console.log(s3 === s4); //false
console.log(s4.description); //foo ,打印描述值,就是声明时传入的值
如果传入的是对象时,会返回对象的toString()值显示
let obj = {
name : 'yolin',
}
let s1 = Symbol(obj)
console.log(s1) //Symbol([object Object])
obj.toString = function(){ //添加一个toString方法
return this.name
}
let s2 = Symbol(obj)
console.log(s2) //Symbol(yolin)
- 声明方式二,Symbol.for(...)。用Symbol.for去声明时,会登记到全局,会先去全局中找有没有一样的描述,如果有就直接返回那个一样的给它,而不会去重新声明一个Symbol
const s1 = Symbol.for('foo');
const s2 = Symbol.for('foo');
console.log(s1 === s2) //true
- Symbol.keyFor 用来判断这个Symbol是否有登记到全局,用Symbol.for声明的就会登记到全局,并返回描述值
const s3 = Symbol('foo');
console.log(Symbol.keyFor(s3)) //undefined
console.log(Symbol.keyFor(s1)) //foo
应用场景
场景1,用姓名作为key,用Symbol属性避免重名覆盖
const st1 = '李四';
const st2 = '李四';
const grade = {
[st1]:{address:'xxx',tel:1111},
[st2]:{address:'xxx',tel:2222},
}
console.log(grade);//第一个李四被第二个李四覆盖
对象的属性名同名时,会自动覆盖上一个。要想同名的信息不被覆盖,可以使用Symbol值作为属性名
const st1 = Symbol('李四');
const st2 = Symbol('李四');
const grade = {
[st1]: { address: 'xxx', tel: 1111 },
[st2]: { address: 'xxx', tel: 2222 },
}
console.log(grade);//使用symbol不会覆盖,因为symbol是唯一的,尽管描述值一样
console.log(grade[st1]);//读取第一个李四信息
console.log(grade[st2])//读取第二个李四信息
2、Symbol属性在一定程度上会被保护起来,使用特殊遍历方法才能遍历到symbol属性,Reflect.ownKeys()
const sym = Symbol('imooc');
class User {
constructor(name) {
this.name = name;
this[sym] = 'imooc.com';
}
getName() {
return this.name + ' ' + this[sym]
}
}
const user = new User('della');
console.log(user)
console.log(user.getName())
// 遍历user属性
for (let key in user) {//读不到symbol属性
console.log(key)
}
for (let key of Object.keys(user)) {//读不到symbol属性
console.log(key)
}
for (let key of Object.getOwnPropertySymbols(user)) {//读symbol属性
console.log(key)
}
for (let key of Reflect.ownKeys(user)) {//既能读到普通属性,又能读到symbol属性
console.log(key)
}
3、应用场景二,消除魔术字符串
function getArea(shape) {
let area = 0;
switch (shape) {
case 'Triangle':
area = 1;
break;
case 'Circle':
area = 2;
break;
}
return area
}
console.log(getArea('Triangle'))//获取三角形面积
用对象属性名消除魔术字符串
const shapeType = {
triangle: Symbol(),//属性值并不重要
circle: Symbol()
}
function getArea(shape) {
let area = 0;
switch (shape) {
case shapeType.triangle:
area = 1;
break;
case shapeType.circle:
area = 2;
break;
}
return area
}
console.log(getArea(shapeType.triangle))//获取三角形面积
console.log(getArea(shapeType.circle))//获取三角形面积
网友评论