1. Symbol是什么
Symbol是ES6 引入了一种新的基本类型,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,前六种是:undefined、null、boolean、string、number、object。
2. Symbol 语法
Symbol([description]) // description为Symbol的描述,不影响Symbol的唯一
3. Symbol的特点
- 独一无二,
Symbol('a')
和Symbol('a')
是不相等的 - 不能使用
new
关键字创建对象,new Symbol()
是不合法的 - Symbol值无法参与运算,无法隐式转成字符串,会报
TypeError
- 作为对象属性无法用
.
运算符,但是可以使用方括号[]
- 作为对象属性,无法被循环遍历,如
for...in
、for...of
,也不会被Object.keys
、Object.getOwnPropertyNames
、JSON.stringify
返回 Object.getOwnPropertySymbols
方法,可以获取对象的所有 Symbol 属性名Reflect.ownKeys
可以返回所有类型的键名,包括常规键名和 Symbol 键名
看下面的例子,加深印象:
const a = Symbol('a');
const b = Symbol('b');
a == b; // false
a + "Hello"; // TypeError: Cannot convert a Symbol value to a string
a.toString() + ""; // Ok,output: 'Symbol()'
const obj = { [a]: 1, [b]: 2, c: 3 };
Object.keys(obj); // ['c']
Object.getOwnPropertySymbols(obj); // [ Symbol(a), Symbol(a) ]
Reflect.ownKeys(obj); // [ 'c', Symbol(a), Symbol(a) ]
JSON.stringify(obj); // '{"c":3}'
const obj2 = { a };
obj2; // { a: Symbol(a) },Key为string,值为Symbol
4. Symbol的使用场景
模拟私有属性
由于Symbol作为对象属性时不参与遍历,而且无法使用字符串key值访问,所以可以模拟私有属性。
js内置对象中也大量使用Symbol,比如Symbol.iterator
,访问对象的迭代器。或者Symbol.toPrimitive
,将对象转成原始值。
在Symbol出现之前,人们经常使用__
前缀来表示私有属性。
消除魔法字符串
假如我们有一个枚举:
const colors = {
RED: 'red',
GREEN: 'green',
BLUE: 'blue'
};
我们用colors.RED
表示红色,只要保证它的值和其他颜色的值不同即可,值是什么不重要,这时就可以用Symbol代替
const colors = {
RED: Symbol(),
GREEN: Symbol(),
BLUE: Symbol()
};
防止属性名冲突
当你想向一个全局对象中添加属性时,你又不知道对象是否包含该属性,就容易覆盖。而使用Symbol作为对象属性可以避免这个问题,因为它的独一无二的。
const global_obj = { a: 1 }
global_obj['a'] = 2; // 覆盖了
const a = Symbol('a');
global_obj[a] = 2; // 不会覆盖,因为Symbol独一无二
你想扩展库的功能,又怕覆盖了它原来的代码,使用Symbol就非常合适。库的作者可能也怕我们乱改库的代码,所以一些重要的代码,比如私有方法,就直接使用Symbol定义了。