前言
Symbol 会生成唯一值,防止属性名出现冲突而产生的,因此在一些自定义组件或三方库中比较容易见到,平时一般也不常用,封装一些特殊组件,也许能有所帮助
Symbol 介绍
Symbol
使用 Symbol 每次创建的值都不一样(使用时,可以把这个对象理解为对象指针作为key,每次创建一定不一样)
const sym = Symbol()
const sym2 = Symbol()
console.log(sym === sym2) //false
Symbol 支持携带描述参数,仅仅是描述参数,不影响其值不一样,通过 description 属性可以获取描述参数
const sym = Symbol('name')
const sym2 = Symbol('name')
console.log(sym === sym2) //false
console.log(sym.description) //name
Symbol.for
Symbol.for() 支持根据描述登记,未登记生成新的,已登记返回登记过的 Symbol,可以理解为加入缓存
const sym = Symbol.for('name');
const sym2 = Symbol.for('name');
console.log(sym === sym2) //true
基础使用案例
如何声明一个 Symbol 属性名,需要注意的是,属性名类型只有 string、symbol,可以说比较固定了,symbol 一个特殊定义的其他类型属性(有点像其他语言中的指针所谓哈希值了🤣)
const symbol = Symbol()
const obj = {
[symbol]: '啦啦啦'
}
console.log(obj[symbol])
遍历
会发现正常遍历无法遍历
const symbol = Symbol();
const obj = {
[symbol]: "啦啦啦",
name: '帅呆了'
};
Object.keys(obj).forEach((item) => {
console.log(item)
})
无法正常遍历不代表无法遍历,可以通过 Object.getOwnPropertySymbols、Reflect.ownKeys 方法获取到
Object.getOwnPropertySymbols 专门获取 Symbol 类型的 key
Reflect.ownKeys 后者是通过反射获取所有的 key
实际应用
为了保护一些参数不被正常遍历到,可以通过设置 Symbol 的方式来存取内容
const special = Symbol();
class User {
constructor(name, idcard) {
this[special] = idcard;
this.name = name;
}
getIdCard() {
return this[special];
}
}
//外部使用
const user = new User('帅', '111111')
console.log(user.getIdCard())
也可以这么改动,根据自己情况选择使用即可
class User {
constructor(name, idcard) {
this[Symbol.for('user_idcard')] = idcard;
this.name = name;
}
getIdCard() {
return this[Symbol.for("user_idcard")];
}
}
//外部使用
const user = new User('帅', '111111')
console.log(user.getIdCard())
扩展
通过 # 修饰的属性名,为私有属性,不能被外部访问到(ts 中的一些标记手段仅仅是ts类型报错,就和早期 _ 开头的标记私有属性一样,有风险,都可以被访问到,只不过多了个ts报错),这个是确实存在的私有属性,如下所示
class Obj {
#name;
lala = '啦啦';
constructor(name) {
// 私有函数
this.#name = name;
}
getName() {
return this.#name;
}
};
const obj = new Obj('名字')
Reflect.ownKeys(obj).forEach((item) => {
console.log(item);
}); //lala
console.log(obj.getName()) //名字