Symbol是一种新引入的原始数据类型,表示独一无二的值,至此也就是说ES2015中有了7中基本数据类型:undefined、null、number、string、boolean、object、symbol。symbol中的引入可以保证一个对象的属性名都是独一无二的,不会发生冲突,不会发生重写。
symbol的声明
let s = Symbol();
同样symbol声明时可以传入一个字符串参数,这个字符串参数的引入是为了使用toString()方法和String()方法将symbol转为字符串时方便区分不同的symbol,因为如果没有这个字符串,转化为字符串时都是“Symbol()”
let s = Symbol();
s.toString();
// Symbol()
s = Symbol('hello');
s.toString();
// Symbol(hello)
symbol作为基本的数据类型,同样可以使用typeof操作符判断数据类型,返回symbol
let s = Symbol();
typeof s;
// symbol
因为symbol表示独一无二的值,所以即使在声明的时候传入了同样的字符串参数,判断相等的时候依旧是返回false
let s1 = Symbol('a');
let s2 = Symbol('b');
s1 == s2;
// false
s1 === s2;
// false
symbol类型不能与其他数据类型进行运算,不过可以将symbol转化为布尔值,当一个symbol声明之后转化为布尔值就是true
let s = Symbol();
Boolean(s);
// true
symbol值非常适合作为一个对象的属性名,当使用symbol作为属性名的时候这时候定义 和获取的时候都应该使用中括号,获取不能使用点运算符,因为点运算符后面始终都是字符串,这与symbol数据类型相悖。定义使用中括号是ES2015中的拓展,定义使用中括号是,属性名可以在这个中括号内进行运算。
以下是三种使用symbol值为属性名的三种定义为对象的方式
let s = Symbol();
//第一种写法
let obj = {};
obj[s] = 'hello';
//第二种写法
let obj = {
[s]: 'hello'
}
//第三种写法
let obj = {};
Object.defineProperty(obj, s, {value: 'hello'});
obj[s];
// hello
注意定义时没有中括号时,这就说明了这是一个普通的字符串属性名,而字符串并不能代表symbol,这时候使用symbol值来方法属性名覆盖和重写的目的就没有实现。
使用symbol作为属性名时,这个属性并不能使用for...in...或者使用for...of...遍历,也不能使用方法Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()返回,返回symbol属性名可以使用ES2015的方法Object.getOwnPropertySymbols()方法返回一个由symbol属性组成的数组。
let obj = {};
let s1 = Symbol('s1');
let s2 = Symbol('s2');
obj[s1] = 'hello';
obj[s2] = 'world';
let arr = Object.getOwnPropertySymbols(obj);
arr;
// [Symbol(s1), Symbol(s2)]
当我们需要重新使用一个symbol值时,可以使用Symbol.for()方法,这个方法接受一个参数作为参数,从而搜索是否有以该字符串为参数声明的symbol值,有则返回,没有则创建一个新的symbol值,需要说明的是这个方法搜索的应该是使用Symbol.for()方法声明的,因为只有使用这个方法声明的才会在全局进行登记,从而提供搜索
let s1 = Symbol('a');
let s2 = Symbol.for('a');
s2 === s1;
// false
let s3 = Symbol('a');
s2 === s3;
// true
最后是一个广告贴,最近新开了一个分享技术的公众号,欢迎大家关注