# **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