符號是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()