Symbol类型那些事
第七种基本数据类型
声明方式
应用场景
/**
* 新的数据类型:Symbol
* <br> 一种新的原始数据类型
* 声明方式
* 应用场景
* @Author: 毛毛
* @Date: 2021-09-10 21:13:12
* @Last Modified by: 毛毛
* @Last Modified time: 2021-09-10 22:57:29
*/
// 现在,原始数据类型有七种了
// Number String Object Boolean Undefined Null Symbol
// TODO 声明方式 1 (注意:Symbol不是构造函数,不能使用new关键字)
const s1 = Symbol();
const s2 = Symbol();
console.log(s1, s2, s1 == s2, s1 === s2);// false
// 声明方式 2 往Symbol函数中定义描述信息 description
const s3 = Symbol('我是s1');
const s4 = Symbol('我是s1');
console.log(s3, s4, s3 == s4, s3 === s4);// false
// 参数对象 会自动调用这个对象的toString方法
const obj1 = {
name: "张三",
toString() {
return this.name;
}
};
const s5 = Symbol(obj1);
console.log(s5);// Symbol(张三)
// Symbol函数的返回值并不是对象,也就是说我们不能操作这个返回值
console.log(s5.name);// undefined
// TODO Symbol()函数的返回值虽然不能使用对象的方法,但是我们可以理解为一个不可重复的字符串
/*
注意,Symbol函数前不能使用new命令,否则会报错。
这是因为生成的Symbol是一个原始类型的值,不是对象。
也就是说,由于Symbol值不是对象,所以不能添加属性。
基本上,它是一种类似于字符串的数据类型。
*/
// 可以获取Symbol函数中的描述
console.log(s3.description); // 我是s1
console.log(s5.description);// 张三
// Symbol.for() 使用该函数声明的Symbol会定义在全局中
// 拿到的返回值 会先去全局中找,如果有,直接返回这个已经声明过的Symbol
// 找不到,才会重新创建新的Symbol
const s6 = Symbol.for('毛毛');
const s7 = Symbol.for('毛毛');
console.log(s6 === s7);//? true
// Symbol.for() 声明的值一直都是在全局环境下的
function getGlobalSymbol() {
return Symbol.for('1');
}
console.log(getGlobalSymbol() === getGlobalSymbol());// true
// Symbol.keyFor(symbol) 判断某个Symbol的返回值是否全局注册过
// 如果没有注册过,返回undefined 注册过 返回该Symbol的description描述
console.log(Symbol.keyFor(s1));// undefined
console.log(Symbol.keyFor(s6)); // Symbol的描述
// TODO 应用场景
// 作为对象的属性,不会出现重复的key
const s8 = Symbol('毛毛');
const s9 = Symbol('毛毛');
const obj2 = {
[s8]: "哈哈",
[s9]: "哈哈",
name: "毛毛"
}
console.log(obj2);//?
// 可以对一个对象的属性进行隐藏
// 使用 for in 是无法遍历到Symbol属性的
for (const k in obj2) {
console.log(k);//只有一个属性被输出出来
}
// Object.keys(obj2) 只能取到一个属性 也不能取到Symbol属性
for (const k of Object.keys(obj2)) {
console.log(k);// name
}
// 使用 Object.getOwnPropertySymbols(obj) 只能获取到该对象的Symbol属性
console.log(Object.getOwnPropertySymbols(obj2));
// 使用 Reflect.ownKeys(obj) 通过反射的形式 可以拿到对象的所有属性 包括 Symbol属性
console.log(Reflect.ownKeys(obj2));// 所有属性
// TODO Symbol还可以消除魔术字符串
// 相同的字符串在代码的很多位置都出现,耦合度比较高 还容易错
// 对应多出出现的字符串,可以使用Symbol进行替换
// 我们要的只是结果,并不关心里面到底是什么值的情况下,就可以使用
const obj3 = {
triangle: Symbol(),
circle: Symbol()
}
function getArea(shape) {
let area = null;
switch (shape) {
// 我们不关心 这个case到底是什么
case obj3.triangle:
area = 1;
break;
case obj3.circle:
area = 2;
break;
}
return area;
}
console.log(getArea(obj3.triangle));