1.概述
ES5 的对象属性名都是字符串,这容易造成属性名的冲突。比如,我们使用了一个他人提供的对象,但又想为这个对象添加新的方法(mixin 模式),新方法的名字就有可能与现有方法产生冲突。如果有一种机制,能够保证每个属性的名字都是独一无二的就好了,这样就能从根本上防止属性名冲突。这就是 ES6引入类型Symbol的原因
Symbol是一种新的原始数据类型,表示独一无二的值。它是JavaScript语言的第七种数据类型,其他六种分别是:Undefined、Null、Boolean、String、Number、Object。
Symbol值是通过Symbol函数生成的,也就是说,对象的属性名现在有两种类型:一种是原来就有的字符串;另一种是新增的Symbol类型,只要属性名属于Symbol类型,就是独一无二的,可以保证不会与其他属性名产生冲突。
如上所示,s是Symbol类型的数据,而不是如字符串之类的其他类型。
需要注意的是:Symbol函数前不能用new命令,否则会报错,这是因为生成的Symbol是一个原始类型的值,不是对象。也就是说,由于Symbol值不是对象,所以不能添加属性。基本上,它是一种类似于字符串的数据类型。
Symbol函数可以接受一个字符串作为参数,表示对Symbol实例的描述,主要是为了在控制台显示,或者转换为字符串时容易区分。
以上代码中,s1和s2是两个Symbol值,如果不加参数,控制台输出的都是Symbol(),不利于区分,此时需要加上参数。
如果Symbol的参数是一个对象,就会调用该对象的toString方法,将其转换成字符串,然后才生成一个Symbol值。
如当传入一个数组和一个对象后,就分别调用了Array和Object的toString方法,将数组和对象分别转换成了字符串再生成了一个Symbol值。实例如下:
Symbol函数的参数只是对当前Symbol值的描述,因此相同参数的Symbol函数的返回值是不相等的。
且Symbol值不能与其他类型的值进行运算,否则会报错;
Symbol值可以显示转化成字符串;
Symbol值也可以转化为布尔值;
Symbol值不能转为数值。
2.Symbol作为属性名
由于每个Symbol值都是不相等的,这意味着Symbol值可以作为标识符用于对象的属性名,保证不会出现同名的属性,这对于一个对象由多个模块构成的情况非常有用,能防止某一个键被不小心改写或覆盖。
var mySymbol=Symbol(); // 第一种写法 var a={}; a[mySymbol]="aaa"; // 第二种写法 var a={ [mySymbol]:"aaa" }; // 第三种写法 var a={}; Object.defineProperty(a,mySymbol,{value:"aaa"}); // 以上写法都得到相同的结果 a[mySymbol]="aaa";
需要注意的是:
(1)Symbol值作为对象属性名时不能使用.运算符。
(2)Symbol值作为属性名时,该属性还是公开属性,不是私有属性。
本文摘自《ES6标准入门(第三版)阮一峰著》