符号是ES6新增的一个数据类型,它经过使用函数 Symbol(符号描述)
来建立。数组
// 建立一个符号 const syb1 = Symbol(); const syb2 = Symbol('这是一个符号'); console.log(syb1,syb2);// Symbol() Symbol(这是一个符号)
符号设计的初衷,是为了给对象设置私有属性。(私有属性:只能在这个歌对象内部的方法里用,别的方法用不了。)dom
举例说明:函数
// 建立一个hero对象 const hero = { attack: 30, // 攻击力 hp: 300, // 血量 defence: 10, // 防护值 gongji() { // 攻击方法:产生伤害 // 伤害:攻击力 * 随机数(0.8 ~ 1.1) const dmg = this.attack * this.getRandom(0.8, 1.1); console.log(dmg); }, getRandom(min, max) { // 根据最小值和最大值产生一个随机数 return Math.random() * (max - min) + min; } }
注意:getRandom方法只是一个工具方法,无需暴露给外部。因此,之前的作法是:工具
const hero = { attack: 30, // 攻击力 hp: 300, // 血量 defence: 10, // 防护值 gongji() { // 攻击方法:产生伤害 // 伤害:攻击力 * 随机数(0.8 ~ 1.1) const dmg = this.attack * this.getRandom(0.8, 1.1); console.log(dmg); function getRandom(min, max){ // 根据最小值和最大值产生一个随机数 return Math.random() * (max - min) + min; } }, }
缺点:this
总结:形成以上缺点的缘由就是由于缺乏了私有属性。prototype
私有属性:只能在对象内部使用,外部没法使用。设计
ES6类的写法也有一样的问题:日志
class Hero { constructor(attack, hp, defence) { this.attack = attack; this.hp = hp; this.defence = defence; } gongji(){ const dmg = this.attack * this.getRandom(0.8, 1.1); console.log(dmg); } getRandom(min, max) { // 根据最小值和最大值产生一个随机数 return Math.random() * (max - min) + min; } }
const syb1 = Symbol('abc'); const syb2 = Symbol('abc'); console.log(syb1 === syb2); // false
const syb1 = Symbol('这是用于对象的一个属性'); const obj = { a: 1, [syb1]: 3 // 符号属性 } console.log(obj); // {a: 1, Symbol(这是用于对象的一个属性): 3}
如何精心设计?
用符号把属性变成私有成员。由于符号是惟一的code
const hero = (function () { const getRandom = Symbol("用于产生随机数的符号"); return { attack: 30, // 攻击力 hp: 300, // 血量 defence: 10, // 防护值 gongji() { // 攻击方法:产生伤害 // 伤害:攻击力 * 随机数(0.8 ~ 1.1) const dmg = this.attack * this[getRandom](0.8, 1.1); console.log(dmg); }, [getRandom](min, max) { // 根据最小值和最大值产生一个随机数 return Math.random() * (max - min) + min; } } }()) hero.gongji(); //hero.getRandom(); // 报错 hero.getRandom is not a function //hero[getRandom](3,5); // 报错 getRandom is not defined
ES6类版:对象
const Hero = (() => { const getRandom = Symbol("用于产生随机数的符号") return class { constructor(attack, hp, defence) { this.attack = attack; this.hp = hp; this.defence = defence; } gongji() { // 攻击方法:产生伤害 // 伤害:攻击力 * 随机数(0.8 ~ 1.1) const dmg = this.attack * this[getRandom](0.8, 1.1); console.log(dmg); } [getRandom](min, max) { // 根据最小值和最大值产生一个随机数 return Math.random() * (max - min) + min; } } })(); const h = new Hero(20, 200, 10);
const syb = Symbol(); const obj = { [syb]: 1, a: 2, b: 3 } for (const prop in obj) { console.log(prop); // a b } console.log(Object.keys(obj)); // ['a','b'] console.log(Object.getOwnPropertyNames(obj)); // ['a','b'] // 获得的是一个符号属性的数组 console.log(Object.getOwnPropertySymbols(obj)); // [Symbol()]
如何获取符号属性?
const Hero = (() => { const getRandom = Symbol("用于产生随机数的符号") return class { constructor(attack, hp, defence) { this.attack = attack; this.hp = hp; this.defence = defence; } gongji() { // 攻击方法:产生伤害 // 伤害:攻击力 * 随机数(0.8 ~ 1.1) const dmg = this.attack * this[getRandom](0.8, 1.1); console.log(dmg); } [getRandom](min, max) { // 根据最小值和最大值产生一个随机数 return Math.random() * (max - min) + min; } } })(); const h = new Hero(3, 6, 3); const sybs = Object.getOwnPropertySymbols(Hero.prototype); //console.log(sybs); // [Symbol(用于产生随机数的符号)] const prop = sybs[0]; console.log(h[prop](3, 5)); // 3.447697709789846
// 有时为了作一些日志记录,看一下哪些符号出了问题 const syb = Symbol(); const str = String(syb); console.log(str); // Symbol()