概述

符号是ES6新增的一个数据类型,它通过应用函数 Symbol(符号形容) 来创立。

// 创立一个符号const syb1 = Symbol();const syb2 = Symbol('这是一个符号');console.log(syb1,syb2);// Symbol() Symbol(这是一个符号)

符号设计的初衷,是为了给对象设置公有属性。(公有属性:只能在这个歌对象外部的办法里用,别的办法用不了。)

举例说明:

// 创立一个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;        }    },}

毛病:

  1. 每一次调用gongji办法都会创立getRandom办法,没有必要始终创立,节约内存空间,只创立一次就好了;
  2. 如果其余办法也要调用getRandom办法,会有点麻烦。

总结:造成以上毛病的起因就是因为短少了公有属性

公有属性:只能在对象外部应用,内部无奈应用。

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}
  • 基于以上特点,开发者能够通过精心的设计,让这些属性无奈通过惯例形式被外界拜访

如何精心设计?
用符号把属性变成公有成员。因为符号是惟一的

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()