符號-普通符號

概述

符號是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()
相關文章
相關標籤/搜索