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