helios741 / myblog

觉得好请点小星星,欢迎有问题交流(issue/email)
109 stars 21 forks source link

ES5中Symbol的用法 #2

Closed helios741 closed 6 years ago

helios741 commented 7 years ago

主要说几个Symbol的使用

消除魔术字符串

先看下面的代码:

function getArea(shape, options) {
    let area = 0
    switch(shape) {
        case 'Triangle':
            area = .5 * options.w * options.h
            break
        /*More case*/
    }
    return area
}

getArea('Triangle', {w: 200, h: 100})

在上面的程序中,我们能看出Triangle就是魔术字符串,我们一般为了消除这种魔术字符串,我们会定义下面的常量:

const shapeType = {
    TRIANGLE: 'Triangle'
}

然后把上面的代码变为:

const shapeType = {
    TRIANGLE: 'Triangle'
}
function getArea(shape, options) {
    let area = 0
    switch(shape) {
        case shapeType.TRIANGLE:
            area = .5 * options.w * options.h
            break
        /*More case*/
    }
    return area
}

getArea(shapeType.TRIANGLE, {w: 200, h: 100})

上面的这种做法的确消除了强耦合。但是我们可以仔细想想,在这种情况之下其实shapeType.TRIANGLE等于哪个值没有影响,所有我们可以把定义的常量变为:

const shapeType = {
    TRIANGLE: Symbol()
}

非私有但只能被内部访问

先看下面的代码:

const size = Symbol('size')

class Collection {
    constructor() {
        this[size] = 0
    }
    add(item) {
        this[this[size]] = item
        this[size]++
    }
    static sizeOf(instance) {
        return instance[size]
    }
}

let x = new Collection()
console.log(Collection.sizeOf(x))

x.add('foo')
x.add('bar')
console.log(Collection.sizeOf(x))

console.log(Object.keys(x)) // ['0', '1']
console.log(Object.getOwnPropertyNames(x)) // ['0', '1']
console.log(Object.getOwnPropertySymbols(x)) // [Symbol(size)]

我们通过keygetOwnPropertyNames都无法获得Symbol的对象,只能通过getOwnPropertySymbols获得。