# **Symbol 类型**   Symbol 是 ES6 新增的一种原始数据类型,它的字面意思是:符号、标记。代表独一无二的值 。   在 ES6 之前,对象的属性名只能是字符串,这样会导致一个问题,当通过 mixin 模式为对象注入新属性的时候,就可能会和原来的属性名产生冲突 。而在 ES6 中,Symbol 类型也可以作为对象属性名,凡是属性名是 Symbol 类型的,就都是独一无二的,可以保证不会与其他属性名产生冲突。     Symbol 值通过函数生成,如下所示: ``` let s = Symbol();//s是独一无二的值 typeof s ;// symbol   ```   和其他基本类型不同的是,Symbol 作为基本类型,没有对应的包装类型,也就是说 Symbol 本身不是对象,而是一个函数。因此,在生成 Symbol 类型值的时候,不能使用 new 操作符 。 Symbol 函数可以接受一个字符串作为参数,表示对 Symbol 值的描述,当有多个 Symbol 值时,比较容易区分。 ``` var s1 = Symbol('s1'); var s2 = Symbol('s2'); console.log(s1,s2);// Symbol(s1) Symbol(s2) ```   注意,Symbol 函数的参数只是表示对当前 Symbol 值的描述,因此,相同参数的 Symbol 函数的返回值也是不相等的。    用 Symbol 作为对象的属性名时,不能直接通过**点**的方式访问属性和设置属性值。因为正常情况下,引擎会把点后面的属性名解析成字符串。 ``` var s = Symbol(); var obj = {};obj.s ='Jack'; console.log(obj);// {s: "Jack"} obj[s] ='Jack'; console.log(obj) ;//{Symbol(): "Jack"} ```   Symbol 作为属性名,该属性不会出现在 for...in、for...of 循环中,也不会被 Object.keys()、Object.getOwnPropertyNames()、JSON.stringify() 返回。但是,它也不是私有属性,有一个 Object.getOwnPropertySymbols() 方法,专门获取指定对象的所有 Symbol 属性名。  ``` var obj = {}; var s1 = Symbol('s1'); var s2 = Symbol('s2'); obj[s1] ='Jack'; obj[s2] ='Tom'; Object.keys(obj);//[]for(var iin obj){ console.log(i);//无输出 } Object.getOwnPropertySymbols(obj);//[Symbol(s1), Symbol(s2)] ```   另一个新的API,Reflect.ownKeys 方法可以返回所有类型的键名,包括常规键名和 Symbol 键名。 ``` var obj = {}; var s1 = Symbol('s1'); var s2 = Symbol('s2'); obj[s1] ='Jack'; obj[s2] ='Tom'; obj.name ='Nick'; Reflect.ownKeys(obj);//[Symbol(s1), Symbol(s2),"name"] ```   有时,我们希望重新使用同一个 Symbol 值,Symbol.for 方法可以做到这一点。它接受一个字符串作为参数,然后全局搜索有没有以该参数作为名称的 Symbol 值。如果有,就返回这个 Symbol 值,否则就新建并返回一个以该字符串为名称的 Symbol 值。 ``` var s1 = Symbol.for('foo'); var s2 = Symbol.for('foo'); s1 === s2//true ``` Symbol.for() 也可以生成 Symbol 值,它 和 Symbol() 的区别是: * Symbol.for() 首先会在全局环境中查找给定的 key 是否存在,如果存在就返回,否则就创建一个以 key 为标识的 Symbol 值 * Symbol.for() 生成的 Symbol 会登记在全局环境中供搜索,而 Symbol() 不会。   因此,Symbol.for()  永远搜索不到 用 Symbol() 产生的值。 ``` var s = Symbol('foo'); var s1 = Symbol.for('foo'); s === s1;// false ``` Symbol.keyFor() 方法返回一个已在全局环境中登记的 Symbol 类型值的 key 。 ``` var s1 = Symbol.for('s1'); Symbol.keyFor(s1);//foo var s2 = Symbol('s2');//未登记的 Symbol 值 Symbol.keyFor(s2);//undefined