js的原始数据类型:unll、undefined、string、number、object、boolean。但是在es6中,新增加了一种数据类型Symbol。
这个symbol是干什么用的呢?在实际编码过程中,我们经常会遇到需要增加新属性的问题,那么我们就必须确保我们新的方法是原来没有的,这个过程其实是挺烦了,稍有不慎,就会破坏代码。神说要有光,于是就有了光。symbol就是为了解决这个的,代表独一无二的值。
let a = Symbol();
console.log(typeof a)
// "symbol"
symbol可以接收一个参数,主要是用来对symbol的描述,可以很容易的区分实例对象
let s1 = Symbol('foo');
let s2 = Symbol('bar');
s1 // Symbol(foo)
s2 // Symbol(bar)
如果不加参数控制台打印出的都会是Symbol(),不容易区分。当然这个只是个参数,并不是说参数相同就代表对象相等
// 没有参数的情况
let s1 = Symbol();
let s2 = Symbol();
s1 === s2 // false
// 有参数的情况
let s1 = Symbol('foo');
let s2 = Symbol('foo');
s1 === s2 // false
可以看到,无论参数怎么样,都不能是对象相等。而且要注意Symbol 值不能与其他类型的值进行运算,会报错。
为了更好的得到symbol中的参数,在es2019中新增了方法description,可以直接获得参数。
const sym = Symbol('foo');
sym.description // "foo"
在使用symbol作为属性名的时候需要注意,不能运用点运算符。
const mySymbol = Symbol();
const a = {};
a.mySymbol = 'Hello!';
a[mySymbol] // undefined
a['mySymbol'] // "Hello!"
为什么a[mySymbol]结果不对呢?因为点运算符后面总是字符串,所以不会读取mySymbol作为标识名所指代的那个值,导致a的属性名实际上是一个字符串,而不是一个 Symbol 值。使用Symbol我们需要使用方括号[]。
let s = Symbol();
let obj = {
[s]: function (arg) { ... }
};
obj[s](123);
上面如果s不放在方括号中,该属性的键名就是字符串s,而不是s所代表的那个 Symbol 值。Symbol 值作为属性名时,该属性是公开属性,不是私有属性。
如果要获取指定对象的Symbol属性使用Object.getOwnPropertySymbols才能获取的到。而且这个方法返回的是一个数组,是该对象里的所有Symbol属性
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)]
除了上面这个方法,另一个新的 API,Reflect.ownKeys
方法可以返回所有类型的键名
let obj = {
[Symbol('my_key')]: 1,
enum: 2,
nonEnum: 3
};
Reflect.ownKeys(obj)
// ["enum", "nonEnum", Symbol(my_key)]
这样也能获取到Symbol属性。