ES6之符号
在ES6之前,一直没有私有属性的概念。对象里的属性全部都可以访问到,所以之前为了区分会加一些特殊的名字如 _ 来进行区分。现在有了一种新的数据类型,叫做符号类型。它可以解决这个问题。
const hero = {
attack: 1,
hp: 100,
defence: 1,
gongji() {
const dmg = this.attack * this.getRandomNum(1, 5);
console.log(`英雄攻击了,造成${dmg}伤害`);
},
getRandomNum(min, max) {
return Math.random() * (max - min + 1) + min;
}
}
// hero.gongji();
const hero2=(function (){
const getRandomNum = Symbol('getRandomNum');
return {
attack: 1,
hp: 100,
defence: 1,
gongji() {
const dmg = this.attack * this[getRandomNum](1, 5);
console.log(`英雄攻击了,造成${dmg}伤害`);
},
[getRandomNum](min, max) {
return Math.random() * (max - min + 1) + min;
}
}
})()
console.log(hero2)
const getRandomNum = Symbol('getRandomNum');
// hero2[getRandomNum](1,2);
const prop=Object.getOwnPropertySymbols(hero2)
console.log(hero2[prop[0]](1,2))
它是如何解决的呢?首先它只能通过调用函数的形式创建,保证了它的唯一性。带有符号类型的属性被叫做符号属性。我们可以通过 typeof 来看到它的类型是 symbol 。symbol 里面的内容叫做符号描述。用来调试和方便理解。
当我们在立即执行函数里创建一个符号类型之后,需要使用计算属性的方式来调用。这时,当我们在外面调用时,就会报错无法调用。因为它只存在于函数作用域内。即使我们使用相同的方式来重新创建一个符号类型也不行,因为符号类型具有唯一性。
同时,为了更好地隐藏这种类型的使用,它是无法被枚举的。只能通过特殊的方法调用。如Object.getOwnPropertySymbols ,通过 Object.getOwnPropertyNames 是无法得到符号属性的。
const prop=Object.getOwnPropertySymbols(hero2)
console.log(hero2[prop[0]](1,2))
当然,如果我们必须得到符号属性可以使用上面的这种方式。
符号类型不能进行隐式转换,但可以进行显式转换。使用 String 构造函数进行转换。
const syb1 = Symbol.for('abc');
const syb2 = Symbol.for('abc');
console.log(syb1 === syb2)
通过 Symbol.for 的方式可以得到共享符号。符号描述相同就会创建一个相同的符号类型。
const SymbolFor = (() => {
const global = {};
return (name) => {
if (!global[name]) {
global[name] = Symbol(name)
}
return global[name]
}
})()
SymbolFor('abc')
通过立即执行函数返回一个判断是否已经存在全局的符号参数,如果存在则使用已经存在的。这就是 Symbol.for 的实现原理。