Symbol
,字面意思是标志。所谓标志,往往是一些标识性强、独一无二的东西。
ES6中引入了Symbol
这样一种新的原始数据类型。用来表示一个独一无二的值。例如
let symbol1 = Symbol();
let symbol2 = Symbol();
console.log(symbol1 === symbol2); //false
首先要注意的是,Symbol()
前面不能加new
关键字。因为Symbol
不是一个对象,而是一个原始的数据类型。其次可以看到,哪怕是调用的同一个Symbol()
函数,返回的两个值也都是不一样的。应该来说,调用Symbol()
返回的值没有哪两个是相同的。
虽然说Symbol
独一无二,但是如果直接输出上面代码中的symbol1
和symbol2
那么得到的结果是一样的,这可能会对后期的调试产生一些困扰。
let symbol1 = Symbol();
let symbol2 = Symbol();
console.log(symbol1); //'Symbol()'
console.log(symbol2); //'Symbol()'
如果想要在输出上做出一些区分,我们可以在初始化的时候传值。
let symbol1 = Symbol('Test');
console.log(symbol1); //’Symbol(Test)‘
如果传入的参数是一个对象的话,那么会默认调用对象的toString
方法。
let obj = {
toString(){
return 'Foo';
}
}
let symbol1 = Symbol(obj);
console.log(symbol1); //Foo
传入的参数可以理解为对Symbol
的一种解释,所以即使是参数相同,返回的Symbol
也是不同的。
Symbol
最大的用处应该是作为对象的属性名了吧。如果说一个对象下有多个模块,很可能会出现模块重复,导致被覆盖的现象。
那么用Symbol
独一无二的特性就可以比较好的解决这个问题。例如
let aSymbol = Symbol();
let obj = {};
obj[aSymbol] = 'foo';
console.log(obj[aSymbol]);
利用Symbol
定义的属性,是用的时候不能用.
运算符。只能和定义时一样用中括号,如上面的代码。
除了定义属性,还能定义对象的方法。例如
let aSymbol = Symbol();
let obj = {
[aSymbol](){};
};
说了这么多关于Symbol
的独一无二,那么有没有什么例外呢?答案肯定是有的。使用Symbol.for
方法。
为Symbol.for
传入一个字符串作为参数,然后该方法就会去搜索有没有使用这个字符串作为解释的Symbol
,有的话直接返回,没有再新建。需要注意的是,若一个Symbol
想要被Symbol.for
搜索到,前提是这个Symbol
是使用Symbol.for
创建的。
例如
let a = Symbol.for('test');
let b = Symbol.for('test');
console.log(a == b); //true
Symbol('test')
和Symbol.for('test')
的区别就在于,前者无论被调用多少遍,返回的都是不同的Symbol
,而后者则返回的都是一样的Symbol
。