symbol类型知识点


为何引入

ES5 的对象属性名都是字符串,这容易造成属性名的冲突。Symbol为新的原始数据类型,通过Symbol函数生成。这就是说,对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的 Symbol 类型。凡是属性名属于 Symbol 类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。

注意

1、生成的 Symbol 是一个原始类型的值,不是对象。也就是说,由于 Symbol 值不是对象,所以不能添加属性。基本上,它是一种类似于字符串的数据类型。所以不能使用new命令
2、Symbol值可以转为布尔值,其他的都不能转

创建

1
2
3
4
5
6
7
8
9
10
let s = Symbol();
s // Symbol()

typeof s
// "symbol"

let s1 = Symbol('foo');
s1 // Symbol(foo),不然就显示 Symbol()
s1.toString() // "Symbol(foo)"
//Symbol函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分。

定义属性名为Symbol的对象和value为Symbol的对象

1
2
3
4
5
6
7
8
9
let a = {
[mySymbol]: 'Hello!',
info: Symbol('info')
};
// 第二种写法
let a = {};
Object.defineProperty(a, mySymbol, { value: 'Hello!' });
// 获取属性值
a[mySymbol] // "Hello!" ,不能使用a.mySymbol

属性名的遍历

只有Object.getOwnPropertySymbols(obj)和Reflect.ownKeys()可以遍历Symbol属性名
for…in,for…of,Object.keys(),Object.getOwnPropertyNames(),JSON.stringify()都不能获取
利用这个特性,可以为对象定义一些非私有的、但又希望只用于内部的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const obj = {};
let a = Symbol('a');
let b = Symbol('b');

obj[a] = 'Hello';
obj[b] = 'World';

const objectSymbols = Object.getOwnPropertySymbols(obj);

objectSymbols
// [Symbol(a), Symbol(b)]
Reflect.ownKeys方法可以返回所有类型的键名,包括常规键名和 Symbol 键名。
const objectKeys = Reflect.ownKeys(obj)
// [Symbol(a), Symbol(b)]