在js中,Symbol是一种基本数据类型,是在ECMAScript 6 (ES6) 中引入的新特性。表示独一无二
Symbol的定义
Symbol是不完整的构造函数,创建symbol对象时不需要new操作符,原因是通过 new 实例化的结果是一个 object 对象,而不是原始类型的 symbol。
var s = Symbol()
typeof s // 'symbol'
Symbol 方法接收一个参数,表示对生成的 symbol 值的一种描述。
var a = Symbol('a')
var b = Symbol('b')
a==b //false
即使是传入相同的参数,生成的 symbol 值也是不相等的,因为 Symbol 本来就是独一无二的意思。
Symbol的应用
- 作为对象的属性
可以作为对象的属性来解决属性覆盖问题,避免引发不必要的代码冲突
var a = Symbol('a')let obj = {}obj[a] = 'test'obj // {Symbol(a): 'test'}
值得注意的是我们无法使用".“来调用对象的Symbol属性,所以必须使用”[]"来访问Symbol属性
- 降低代码耦合
当代码中充斥着大量的魔法字符时,纵使是原开发者在经过一段时间后再回头看也会变得难以理解,更不必说是交由后来开发者维护。
假如现有一个 Tabs 切换的功能:
if (type === 'basic') {return <div>basic tab</div>
}if (type === 'super') {return <div>super tab</div>
}
上面代码中字符串 basic、super 就是与业务代码无关的魔法字符,接下来使用 Symbol 对这块代码进行改造。
const tabTypes = {basic: Symbol(),super: Symbol(),
}if (type === tabTypes.basic) {return <div>basic tab</div>
}if (type === tabTypes.super) {return <div>super tab</div>
}
全局共享Symbol
如果我们想创建一个可供全局使用的symbol,那么我们需要用Symbol.for(),可以传递一个参数作为描述,该方法可以遍历全局注册表中的的Symbol,当搜索到相同描述,那么会调用这个Symbol,如果没有搜索到,就会创建一个新的Symbol。
const a = Symbol.for('a')
const b = Symbol.for('a')
a === b // true
过程解析
1、首先通过Symbol.for()在全局注册表中寻找描述为a的Symbol,而目前没有符合条件的Symbol,所以创建了一个描述为a的Symbol
2、当声明b并使用Symbol.for()在全局注册表中寻找描述为a的Symbol,找到并赋值
3、比较a与b结果为true反映了Symbol.for()的作用
再来看看下面一段代码
const a = Symbol('a')
const b = Symbol.for('a')
a === b // false
结果是false,与上面的区别仅仅在于第一个Symbol的创建方式,我们来分析。
1、使用Symbol(‘a’)直接创建,所以该Symbol(‘a’)不在全局注册表中
2、使用Symbol.for(‘a’)在全局注册表中寻找描述为a的Symbol,并没有找到,所以在全局注册表中又创建了一个描述为a的新的Symbol
3、秉承Symbol创建的唯一特性,所以a与b创建的Symbol不同,结果为false
Symbol.keyFor()获取全局注册表变量的描述
const a = Symbol('a')
const b = Symbol.for('a')
Symbol.keyFor(a) // undefined
Symbol.keyFor(b) // a
symbol对象不能用于数据运算,包括+、-、*、/等
const a = Symbol('a')
a+0 //Uncaught TypeError: Cannot convert a Symbol value to a number