符号-普通符号

概述

符号是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方法只是一个工具方法,无需暴露给外部。因此,之前的作法是:工具

  1. 给这些方法命名时前面加符号,好比$getRandom、@getRandom、 _getRandom
  2. 不暴露给外部的方法用以下写法 :
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

  1. 每一次调用gongji方法都会建立getRandom方法,没有必要一直建立,浪费内存空间,只建立一次就行了;
  2. 若是其余方法也要调用getRandom方法,会有点麻烦。

总结:形成以上缺点的缘由就是由于缺乏了私有属性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;
    } 
}

特色

  1. 没有字面量
    只能经过Symbol()建立
  2. 使用typeof获得的类型是 symbol
  3. 每次调用Symbol函数获得的符号永远不相等,不管符号名是否相同
const syb1 = Symbol('abc');
const syb2 = Symbol('abc');

console.log(syb1 === syb2); // false
  1. 符号能够做为对象的属性名存在,这种属性称之为符号属性
    对象的属性确定是字符串,如今多了一个符号属性。
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);
  • 符号属性是不能枚举的,所以在for-in循环中没法读取到符号属性,Object.keys方法也没法读取到符号属性;
  • getOwnPropertyNames尽管能够获得全部没法枚举的属性,可是仍然没法读取到符号属性
  • ES6新增Object.getOwnPropertySymbols方法,能够读取符号
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
  1. 符号没法被隐式转换,所以不能被用于数学运算、字符串拼接或其余隐式转换的场景,但符号能够显示的转换为字符串,经过 String 构造函数进行转换便可,console.log 之因此能够输出符号,是它在内部进行了显示转换
// 有时为了作一些日志记录,看一下哪些符号出了问题
const syb = Symbol();
const str = String(syb);
console.log(str); // Symbol()
相关文章
相关标签/搜索