ECMAScript 6 中新的变量类型 Symbol[1],挺有意思的。以前只是看了几下,但没怎么使用。乘着空闲,研究了一下。
Symbol 最重要的特性就是它的唯一性。你无法初始化同样的 Symbol 变量,这点跟对象是一样的。
1234567891011const sb1 = Symbol('symbol')const sb2 = Symbol('symbol')sb1 === sb2 // falseconst obj1 = {}const obj2 = {}obj1 === obj2 // false
Symbol 还可以用作对象中的属性名。
123456789101112131415const prop_value = Symbol('value')const prop_plus = Symbol('plus')const calc = { [prop_value]: 0, [prop_plus] (val) { return this[prop_value] += val },}calc[prop_plus](10)calc[prop_plus](7)console.log(calc[prop_value]) // output: 17
注意,此时 calc 对象中 prop_value
、prop_plus
都不是字符串类型的属性名。而是 Symbol 类型的。并且 Object.keys()
无法获得 Symbol 值。for in
也无法遍历,Object.getOwnPropertyNames()
、JSON.stringify()
亦如此。[2]
12345678910111213console.log( Object.keys(calc) ) // output: []const obj_keys = []for (let key in calc) { obj_keys.push( key )}console.log( obj_keys ) // output: []console.log( Object.getOwnPropertyNames(calc) ) // output: []console.log( JSON.stringify( calc ) ) // output: "{}"
Symbol 属性支持原型链。有意思的是 Object.assign
能「取得」Symbol 属性。
1234567const calc_chain = Object.create(calc)console.log(calc_chain[prop_value]) // output: 17const calc_mixin = Object.assign({}, calc)console.log(calc_mixin[prop_value]) // output: 17console.log(calc_mixin === calc) // output: false
因为常规方法无法获得 Symbol 属性。所以我想到可以做到「私有属性」的作用。
1234567891011121314151617181920const new_calc = (function () { const prop_value = Symbol('value') return { [prop_value]: 0, reset () { this[prop_value] = 0 }, plus (val) { return this[prop_value] += Number(val) }, get () { return this[prop_value] }, }})()
因为在匿名函数外部无法获取 prop_value
,所以无法在外部修改 new_calc[prop_value]
的值。