你真的会用 ES6 的 Symbol 吗?

263 阅读1分钟

ES6 Symbol数据类型,相信很多人都了解概念,但总不知道在哪可以使用到它。

今天我们就来聊聊,Symbol在实际的开发里可以怎么玩?

一、消除魔术字符串

一般消除魔术字符串的写法是:

const formAKey = 'a-form-key';
const formBKey = 'b-form-key';
const forms = {
    formAKey: {      
        getValue: () => {
            return 'I am form A';
        }
    },
    formBKey: {      
        getValue: () => {
            return 'I am form B';          
        }
    }
}

forms.formAKey.getValue() // I am form A
forms.formBKey.getValue() // I am form B

如果forms是全局的,那么你需要考虑一旦重复引起的属性覆盖问题。

由于我们根本不需要关心每次创建的Form key叫什么名字,不冲突即可,有了Symbol我们可以写成这样:

const formAKey = Symbol();
const formBKey = Symbol();
const forms = {
    [formAKey]: {        
        getValue: () => {
            return 'I am form A';
        }
    },
    [formBKey]: {
        getValue: () => {
            return 'I am form B';          
        }
    }
}

forms[formAKey].getValue() // I am form A
forms[formBKey].getValue() // I am form B

二、类的私有属性

由于Symbol的特殊性,当它作为属性值时不会被常规方法遍历得到,所以我们可以利用它来做私有属性,只供内部使用

const sex = Symbol();
class Human {
    constructor(){
        this.age = 18;
        this[sex] = 'female';
    }
    getSex(){
        return this[sex];
    }
}
const human = new Human();

human.sex // undefined
human.getSex() // female
Object.keys(human) // ['age']

然而还是有一点缺陷,ES6的另一个新特性可以获取到它:Reflect

Reflect.ownKeys(human) // [ 'age', Symbol() ]
human[Reflect.ownKeys(human)[1]] // female

三、共享体系

Symbol也可以做全局共享,那就是Symbol.for(),它接受一个字符串作为参数,然后搜索有没有以该参数作为名称的 Symbol 值。如果有,就返回这个 Symbol 值,否则就新建一个以该字符串为名称的 Symbol 值,且登记在全局环境中供搜索。

const zhangsan = Symbol.for('China');
const chinese = { 
    [zhangsan]: 'I come from China'
 };
const lisi = Symbol.for('China');

chinese[zhangsan] // I come from China
chinese[lisi] // I come from China