目标
- 使用符号作为常量
- 使用符号作为对象键
- 使用全局符号创建行为钩子
- 使用公知符号修改对象行为
符号symbol
作为添加在ES6中的新原语,是js有史以来第一个新增的原语,用来钩住内置js对象的行为的唯一值,分为三类:
- 唯一符号
- 去全局符号
- 公知符号
使用符号作为常量
在以前我经常会使用flag来作为标志,标志一个特殊变量,用作识别,但是会增加命名冲突的可能性
const position_main={
TOP:'top',
BOTTOM:'bottom'
}
const position_other={
T:'top',
L:'left'
}
function addToolTip(position){
switch(position){
case position_main.TOP:
console.log(`添加在上面`);
break;
case position_main.BOTTOM:
console.log(`添加在下面`);
break;
default:
throw new Error(`出错了`);
break;
}
}
addToolTip(position_other.T)
//此处我们本来是想输出错误信息,但是他与主要的position_main也匹配了
原因:标志不是唯一的
解决办法:使用唯一符号解决命名冲突问题,创建唯一符号,每一个符号都是独特的
Symbol()===Symbol() //false
Symbol('top')===Symbol('top') //false
调用Symbol函数时,每次都在内存中创建了新的值,因此新的符号永远不会等同于内存中其他地方的另一个符号Symbol创建的符号,永远不会发生冲突
//重写上面案例
const position_main={
TOP:Symbol('top'),
BOTTOM:Symbol('bottom')
}
const position_other={
T:'top',
L:'left'
}
function addToolTip(position){
switch(position){
case position_main.TOP:
console.log(`添加在上面`);
break;
case position_main.BOTTOM:
console.log(`添加在下面`);
break;
default:
throw new Error(`出错了`);
break;
}
}
addToolTip(position_other.T) //Error: 出错了 因为是position_main.TOP唯一值
使用符号作为对象键
开发者会使用前导下划线给对象添加属性,以此表示他们是作为私有属性存在的,如:
Store._internals
,但是除非使用Object.defineProperty
指定,否则这些值是枚举的,意味着他们仍然可以通过for..in
或者JSON.stringify()
使用
我们可以使用符号作为属性名称得到相同的伪私有属性
const Store={
[Symbol('_internals')]:{
//.....使用符号作为属性名称时,必须是计算属性名称
}
}
此时属性是不可枚举的
构建锁和钥匙系统
每个所都有自己的唯一钥匙,锁中保留了一些秘密数据,只有正确的钥匙访问时,才会被打开并返回数据
- lock函数接受单个参数secret,指锁定的数据
- 使用正确的钥匙调用,它会返回唯一的钥匙key和打开后的秘密unlock函数
- {key,unloack}=lock(secret)
首先确定secret钥匙的数据类型,我们使用Symbol
function lock(secret) { const key = Symbol('key'); return { key, unlock(keyUsed) { if (keyUsed === key) { return secret; } else { return '*'.repeat(secret.length || secret.toString().length) } } } } const { key, unlock } = lock('JavaScript!') console.log(unlock(key)); //JavaScript! console.log(unlock()); // ***********