## 概述
在ES5中,所有的屬性名使用的都是標準的字符串,如果你想修改一個別人提供的對象,并且為這個對象增加一個方法的時候,你就要非常小心了,因為你可能選擇了一個已經存在的方法的名字。因此在ES6中引入了Symbol這個類型,當你使用Symbol類型來定義類的屬性或者方法名的時候,ES6將保證這個屬性和方法名稱是全局唯一的。
### 創建Symbol實例
```javascript
# 第一種方法直接使用Symbol構造函數
var s1 = Symbol();
# 為創建的Symbol對象指定一個名稱
var s2 = Symbol("test");
# 使用這種方法,每次創建出來的Symbol對象都是不一樣的
var s3 = Symbol("test");
# console.log(s2 == s3)將返回false
# 第二種方法,使用Symbol.for方法來創建Symbol實例
# 使用Symbol.for方法來創建一個Symbol實例的時候,
# 系統首先會在一個全局的注冊表中查找是否有相同Key名稱的Symbol被創建了,如果找到,就返回已經存在的對象
# 否則,將創建一個全新的對象
s1 = Symbol.for("test")
s2 = Symbol.for("test")
console.log(s1 == s2) //will return true
console.log(s1 == s3) // will return false,因為s3是通過Symbol調用產生的
```
在我們了解了ES6為什么需要引入Symbol對象之后,讓我們來看一些具體的例子來增加一些對Symbol對象的感性的認識。
## 引用實例1 --- 對象的屬性
### 使用Symbol來定義類的屬性
```javascript
var a = {};
var s1 = Symbol("test");
a[s1] = "hello world!";
console.log(a[s1]); //this will print "Hello World!"
```
**需要注意的是,當使用Symbol作為屬性名的時候,一定要用[]來進行引用,如果你用.(點號)進行引用,那么產生的屬性名實際是一個字符串,和Symbol對象本身沒一點關系**
### 遍歷使用Symbol來定義的屬性
因為Symbol對象不是一個字符串,所以原先的**Object.getOwnPropertyNames()**方法并不會返回它們,你需要使用專門的**Object.getOwnPropertySymbols()**方法來訪問它們。
```javascript
var a = {};
var s1 = Symbol("test");
var s2 = Symbol("testfunc");
a[s1] = "hello world!";
a[s2] = function(){
console.log("Test function");
};
//below code will return []
console.log(Object.getOwnPropertyNames(a));
//below code will return [Symbol(test), Symbol(testfunc)]
console.log(Object.getOwnPropertySymbols(a));
```
## 引用實例2 --- 消除魔術字符串
魔術字符串指的是在代碼中反復出現的相同的字符串,對一個結構良好的代碼來說,應該盡量消除魔術字符串的存在,而使用常量作為替代。下面就讓我們來看一個具體的例子來了解如何使用Symbol來消除代碼中的魔術字符串。 在代碼中我們嘗試根據輸入信息的不同返回不同的Hello
```javascript
# 引入Symbol前的代碼
# 在這個代碼中es, ch就是魔術字符串
# 當你在調用這個函數的時候,必須確保輸入的參數是一個有效的魔術值
function getHello(country){
switch(country){
case "es":
return "Holla";
case "ch":
return "你好";
default:
return "Hello";
}
}
console.log(getHello("es"));
console.log(getHello("ch"));
```
```javascript
# 引入Symbol之后的代碼
# 在這個代碼中es, ch不再是一個具體的字符串
# 因此不管在COUNTRY_CODE中如何修改es, ch的定義,調用方的代碼都不需要修改
const COUNTRY_CODE= {
es: Symbol(),
ch: Symbol()
}
function getHello(country){
switch(country){
case COUNTRY_CODE.es:
return "Holla";
case COUNTRY_CODE.ch:
return "你好"
default:
return "Hello"
}
}
console.log(getHello(COUNTRY_CODE.es));
console.log(getHello(COUNTRY_CODE.ch));
```
## ES6內置的Symbol實例
### Symbol.hasInstance
對對象使用instanceof調用的時候,在ES6內部調用的是obj[Symbol.hasInstance]方法
### Symbol.isConcatSpreadable
決定調用Array.prototype.contact方法的時候,對象是否可以展開
```javascript
var arr1 = [1, 2];
[3, 4].concat(arr1); // return [3, 4, 1, 2]
arr1[Symbol.isConcatSpreadable] = false;
[3, 4].concat(arr1); // return [3, 4, [1, 2]]
```
### 和字符串操作相關的Symbol
* Symbol.replace指向一個方法,將被String.prototype.replace調用
* Symbol.search指向一個方法,將被String.prototype.search調用
* Symbol.split指向一個方法,將被String.prototype.split調用
* Symbol.match指向一個方法,將被str.match(object)調用
* Symbol.toStringTag只想一個方法,將被Object.prototype.toString調用
### Symbol.iterator
指向對象的默認遍歷器
### Symbol.toPrimitive
指向一個方法,將對象轉換成一個primitive類型的值。這個方法將接受一個hint參數,表示要轉換成哪種primitive類型,具體的value包括"Number", "String", "Default"
### Symbol.unscopables
指向一個屬性,這個屬性返回一個JSON對象,表示該對象的哪些屬性將被with環境排除在外,下面是一個具體的例子。
```javascript
# when Test has no Symbol.unscopables
class Test{
saySomething() { return "abc"; }
}
var saySomething = function() { return "123"; }
with(Test.prototype){
saySomething(); // return "abc"
}
# when Test has Symbole.unscopables
class Test{
saySomething() { return "abc"; }
get [Symbol.unscopables] {
return {saySomething: true};
}
}
with(Test.prototype){
saySomething(); // now return "123"
}
```
- Introduction
- Nodejs 4.x新特性
- classes
- typed arrays
- generators
- collections
- Set
- Map
- arrow functions
- block scoping
- template strings
- promises
- symbols
- Koa基礎
- 上下文
- koa-generator
- 安裝
- 創建項目
- 更改視圖模板引擎
- Routes
- HTTP
- Get
- 如何獲取query參數
- 如何獲取params
- Post
- 從post獲取參數
- 標準表單(Post with x-www-form-urlencoded)
- 文件上傳(Post with form-data)
- Post with raw
- 數據庫
- MySQL
- Mongo
- 流程控制
- generator/co
- es6的generator是什么?
- co = generator + promise
- async/await
- promise with bluebird
- 測試
- Mocha
- Supertest
- 部署
- 最佳實踐
- FAQ
- 如何發布本書到git pages
- 如何知道require模塊的用法
- koa中的異常處理