多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
  本节将会重点分析ES6引入的第6种基本类型:Symbol(符号)。符号可以像字符串那样作为对象的属性名,只是它有唯一性的特点,可以避免属性名之间的冲突。 ## 一、创建   符号没有字面量形式,只能通过Symbol()函数创建。该函数有一个可选的参数,只是用来描述当前符号,除了便于阅读之外,没有其他用途。由此可知,即使两个符号的描述相同,它们还是不能画等号。注意,Symbol()不是构造函数,因此不能和new运算符组合使用,否则会抛出类型错误。下面用一个例子展示符号的创建。 ~~~ var sym1 = Symbol(), sym2 = Symbol("name"), sym3 = Symbol("name"), sym4 = new Symbol(); //抛出类型错误 console.log(sym2 === sym3); //false ~~~   如果要识别一个变量是否为符号,可以用typeof运算符。ES6扩展了它,当检测到符号时,能返回一个新的类型字符串“symbol”,具体如下所示。 ~~~ typeof sym1; //"symbol" typeof sym2; //"symbol" ~~~ ## 二、类型转换   符号在类型转换时表现得并不灵活,它无法与数字或字符串进行运算,也无法显式的转换成数字。如下所示,后面四条语句在执行时都会报错。 ~~~ var sym = Symbol("age"); Number(sym); parseInt(sym); 1 + sym; "" + sym; ~~~   不过,符号可以显式的转换成字符串或布尔值,具体如下所示。 ~~~ Boolean(sym);   //true !sym;   //false sym.toString(); //"Symbol(age)" String(sym); //"Symbol(age)" ~~~ ## 三、全局共享   ES6会在内部维护一张全局符号注册表,通过Symbol.for()方法,可以登记指定符号,使其变成一个全局有效地符号,从而达到全局共享。该方法只接收一个参数,这个参数既是注册表中的键值,同时也是此符号的描述。下面的代码调用了两次Symbol.for()方法,传递了相同的参数,返回的却是同一个全局符号。 ~~~ var sym1 = Symbol.for("name"), sym2 = Symbol.for("name"); console.log(sym1 === sym2); //true ~~~   在上面的代码中,第一次调用Symbol.for()方法时,会在注册表中搜索键值为“name”的符号,由于没有找到,所以就会创建一个新的符号。而在第二次调用Symbol.for()方法时,由于传递的键值与前一次相同,因此会返回刚刚的那个符号。从而可知,对变量sym1和sym2进行全等比较,返回的结果将是true。   如果要获取某个全局符号所对应的键值(即它的描述),那么可以通过Symbol.keyFor()实现,具体操作如下所示。 ~~~ Symbol.keyFor(sym1); //"name" Symbol.keyFor(sym2); //"name" ~~~ ## 四、属性名   本节开头曾提到过对象的属性名可以用符号表示,而这类属性可以有三种赋值方式。第一种是用方括号,注意,不能用点号,因为点号后面的标识符会被识别成字符串而不是符号。下面代码分别用方括号和点号为obj对象的sym属性赋值,前者被识别成了符号属性,而后者却被识别成了字符串属性。 ~~~ var sym = Symbol("name"), obj = {}; obj[sym] = "strick"; obj.sym = "strick"; console.log(obj); //{Symbol(name): "strick", sym: "strick"} ~~~   第二种是在创建对象字面量时,用计算属性名的方式(即属性名被方括号包裹)为其赋值,如下所示。 ~~~ obj = { [sym]: "freedom" }; ~~~   第三种是调用Object.defineProperty()或Object.defineProperties()方法来为符号属性赋值,如下所示。 ~~~ Object.defineProperty(obj, sym, { value: "justice" }); ~~~   注意,符号属性是不可枚举的,既不能被for-in等循环遍历到,也不能被Object.keys()、Object.getOwnPropertyNames()等方法读取到。但可以通过Object.getOwnPropertySymbols()方法获得对象的符号属性,具体如下所示。 ~~~ obj = { [sym]: "freedom", age: 28 }; Object.keys(obj);    //["age"] Object.getOwnPropertyNames(obj); //["age"] Object.getOwnPropertySymbols(obj); //[Symbol(name)] ~~~ ## 五、内置符号   ES6提供了一些内置符号,也叫做知名符号(Well-Known Symbol)。它们暴露了语言的内部逻辑,允许开发人员修改或拓展规范所描述的对象特征或行为。每一个内置符号对应Symbol对象的一个属性,例如Symbol.hasInstance、Symbol.iterator等,表1列出了11个内置符号。 :-: ![](https://img.kancloud.cn/11/ce/11cef089950c526004b71da5a78615eb_1330x882.png) 表1 内置符号   下面会给出4个内置符号的示例,分别是hasInstance、isConcatSpreadable、match和toStringTag。 ~~~ let digit = { [Symbol.hasInstance](number) { return !(number % 2); //判断数字是否为偶数 } }; 1 instanceof digit; //false 2 instanceof digit; //true let arr1 = [3, 4]; [1, 2].concat(arr1); //[1, 2, 3, 4] let arr2 = [3, 4]; arr2[Symbol.isConcatSpreadable] = false; //禁止展开 [1, 2].concat(arr2); //[1, 2, [3, 4]] let regex = { [Symbol.match](str) { return str.substr(0, 10); } }, message = "My name is strick"; message.match(regex);  //"My name is" let people = { [Symbol.toStringTag]: "People" }; people.toString(); //"[object People]" ~~~ ***** > 原文出处: [博客园-ES6躬行记](https://www.cnblogs.com/strick/category/1372951.html) [知乎专栏-ES6躬行记](https://zhuanlan.zhihu.com/pwes6) 已建立一个微信前端交流群,如要进群,请先加微信号freedom20180706或扫描下面的二维码,请求中需注明“看云加群”,在通过请求后就会把你拉进来。还搜集整理了一套[面试资料](https://github.com/pwstrick/daily),欢迎浏览。 ![](https://box.kancloud.cn/2e1f8ecf9512ecdd2fcaae8250e7d48a_430x430.jpg =200x200) 推荐一款前端监控脚本:[shin-monitor](https://github.com/pwstrick/shin-monitor),不仅能监控前端的错误、通信、打印等行为,还能计算各类性能参数,包括 FMP、LCP、FP 等。