符号-普通符号

概述

符号是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()
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 222,000评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,745评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,561评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,782评论 1 298
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,798评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,394评论 1 310
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,952评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,852评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,409评论 1 318
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,483评论 3 341
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,615评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,303评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,979评论 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,470评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,571评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,041评论 3 377
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,630评论 2 359