tip 文章是翻譯,主要是很多 ES6 的用法技巧以及最佳實(shí)踐~https://github.com/DrkSephy/es6-cheatsheet 
ES6 手冊(cè) 這篇手冊(cè)包含了 ES2015(ES6) 的使用小技巧、最佳實(shí)踐以及可以給你每天的工作參考的代碼片段。
內(nèi)容列表 var 和 let/const 的比較 除了 var ,我們現(xiàn)在還可以使用兩個(gè)新的標(biāo)示符來定義一個(gè)變量 —— let 和 const。和 var 不一樣的是,let 和 const 不存在變量提升。
使用 var 的栗子:
var  snack = 'Meow Mix' ;function  getFood (food)      if  (food) {         var  snack = 'Friskies' ;         return  snack;     }     return  snack; } getFood(false ); // undefined  
當(dāng)我們用 let 代替 var 的時(shí)候,觀察會(huì)發(fā)生什么:
let  snack = 'Meow Mix' ;function  getFood (food )     if  (food) {         let  snack = 'Friskies' ;         return  snack;     }     return  snack; } getFood(false ); // 'Meow Mix'  
當(dāng)我們重構(gòu)使用 var 的老代碼的時(shí)候應(yīng)該注意上面的變化。盲目地使用 let 替換 var 可能會(huì)出現(xiàn)出乎意料的情況。
注意 : let 和 const 是塊級(jí)作用域,因此在變量未被定義之前使用它會(huì)產(chǎn)生一個(gè) ReferenceError。
console .log(x); //  ReferenceError : x is  not  definedlet x = 'hi' ; 
最佳實(shí)踐 : 在遺留代碼中放棄使用 var 聲明意味著需要很小心地重構(gòu);在新的項(xiàng)目代碼中,使用 let 聲明一個(gè)可以改變的變量,用 const 聲明一個(gè)不能被重新賦值的變量。
用塊級(jí)作用域代替 IIFES 函數(shù)立即執(zhí)行表達(dá)式  的通常用途是創(chuàng)造一個(gè)內(nèi)部的作用域,在 ES6 中,我們能夠創(chuàng)造一個(gè)塊級(jí)作用域而不僅限于函數(shù)作用域:
IIFES:
(function  (     var  food = 'Meow Mix' ; }()); console .log(food); // Reference Error 
使用 ES6 的塊級(jí)作用域:
{     let  food = 'Meow Mix' ; } console .log(food); // Reference Error 
箭頭函數(shù) 我們經(jīng)常需要給回調(diào)函數(shù)維護(hù)一個(gè)詞法作用域的上下文 this。
function  Person (name)      this .name = name; } Person.prototype.prefixName = function  (arr)       return  arr.map(function  (character)           return  this .name + character; // Cannot read property 'name' of undefined      }); }; 
一個(gè)常用的解決辦法是把 this 存在一個(gè)變量中:
function  Person (name)      this .name = name; } Person.prototype.prefixName = function  (arr)       var  that = this ; // Store the context of this      return  arr.map(function  (character)           return  that.name + character;     }); }; 
我們也可以傳遞一個(gè)合適的 this 上下文:
function  Person (name)      this .name = name; } Person.prototype.prefixName = function  (arr)       return  arr.map(function  (character)           return  this .name + character;     }, this ); } 
我們還可以綁定上下文:
function name ) {    this.name  = name ; } Person.prototype.prefixName = function      return  arr.map(function character ) {         return  this.name  + character ;     }.bind (this)); }; 
使用 箭頭函數(shù) ,this 將不會(huì)受到影響,并且我們可以重寫上面的函數(shù):
function name ) {    this.name  = name ; } Person.prototype.prefixName = function      return  arr.map(character  => this.name  + character ); }; 
最佳實(shí)踐 :當(dāng)你需要維護(hù)一個(gè) this 上下文的時(shí)候使用 箭頭函數(shù) 。
在我們寫一個(gè)函數(shù)的時(shí)候,箭頭函數(shù)更加簡(jiǎn)潔并且可以很簡(jiǎn)單地返回一個(gè)值:
var  squares = arr.map(function  (x)  return  x * x }); // Function Expression 
const  arr = [1 , 2 , 3 , 4 , 5 ];const  squares = arr.map (x => x * x); // Arrow Function for terser implementation 
最佳實(shí)踐 :盡可能使用箭頭函數(shù)代替原來的寫法。
字符串 在 ES6 中,標(biāo)準(zhǔn)庫升級(jí)了很多,在這些變化中有許多新的對(duì)于字符串的函數(shù),比如 .includes() 和 .repeat()。
.includes( ) var  string  = 'food' ;var  substring = 'foo' ;console. log (string . indexOf(substring) > -1 ); 
之前我們使用 indexOf() 函數(shù)的返回值是否 >-1 來判斷字符串是否包含某些字符串,現(xiàn)在我們更簡(jiǎn)單地使用 .includes() 來返回一個(gè)布爾值來判斷:
const string  = 'food' ; const substring  = 'foo' ; console.log (string .includes(substring )); // true  
.repeat( ) function repeat (string , count ) {     var strings = [];     while (strings.length  <>count ) {         strings.push(string );     }     return  strings.join('');} 
在 ES6 中,可以更簡(jiǎn)便地實(shí)現(xiàn):
// String.repeat(numberOfRepetitions) 'meow' .repeat (3) ; // 'meowmeowmeow' 
模版字符串 使用 模版字符串  我們就可以不用對(duì)某些特殊自負(fù)進(jìn)行轉(zhuǎn)義處理了:
var text  = 'This string contains \' double  quotes\' which are escaped.' ; 
let  text = `This  string  contains 'double quotes'  which don't need to  be escaped anymore.`;
模版字符串  還支持插入,可以把變量值和字符串連接起來.
var  name = 'Tiger' ;var  age = 13 ;console .log('My cat is named '  + name + ' and is '  + age + ' years old.' );
更簡(jiǎn)單:
const  name = 'Tiger' ;const  age = 13 ;console .log(`My cat is named ${name}  and is ${age}  years old.` );
在 ES5 中,需要換行時(shí),需要這樣:
var text = (     'cat \n' +     'dog \n' +     'nickelodeon'  ); 
或者這樣:
var  text = [    'cat' ,     'dog' ,     'nickelodeon'  ].join ('\n' ); 
模版字符串  可以支持換行并且不需要額外的處理:
let text = ( `c at dog nickelodeon` ;  
模版字符串  還支持表達(dá)式:
let  today = new  Date ();let  text = `The time  and  date  is  ${today.toLocaleString()}`;
解構(gòu) 結(jié)構(gòu)可以讓我們用一個(gè)更簡(jiǎn)便的語法從一個(gè)數(shù)組或者對(duì)象(即使是深層的)中分離出來值,并存儲(chǔ)他們。
結(jié)構(gòu)數(shù)組 var  arr1 , 2 , 3 , 4 ];var  a0 ];var  b1 ];var  c2 ];var  d3 ];
let [a, b, c, d] = [1 , 2 , 3 , 4 ]; console.log (a); // 1  console.log (b); // 2  
結(jié)構(gòu)對(duì)象 var  lukevar  occupation// 'jedi' var  father// 'anakin' 
let  luke = { occupation: 'jedi' , father: 'anakin'  };let  {occupation, father} = luke;console .log(occupation); // 'jedi' console .log(father); // 'anakin' 
模塊 在 ES6 之前,我們使用 Browserify 這樣的庫來創(chuàng)建客戶端的模塊化,在 node.js 中使用 require。
使用 CommonJS 的出口 module .exports  =1 ;module .exports  =module .exports  =module .exports  =function  bar  ()  {
使用 ES6 的出口 在 ES6 中我們可以暴漏多個(gè)值,使用 Exports:
export  let  name = 'David' ;export  let  age  = 25 ;??
或者暴露一個(gè)對(duì)象列表:
function  sumTwo (a, b )     return  a + b; } function  sumThree (a, b, c )     return  a + b + c; } export  { sumTwo, sumThree };
我們還可以暴露函數(shù)、對(duì)象和其他的值,通過簡(jiǎn)單地使用 export 這個(gè)關(guān)鍵字:
export  function  sumTwo (a, b )     return  a + b; } export  function  sumThree (a, b, c )     return  a + b + c; } 
最后,我們還可以綁定一個(gè)默認(rèn)的輸出:
function  sumTwo (a, b )     return  a + b; } function  sumThree (a, b, c )     return  a + b + c; } let  api = {    sumTwo,     sumThree }; export  default  api;/* Which is the same as  * export { api as default };  */ 
最佳實(shí)踐 :總是在模塊的最后面使用 export default 方法,這可以讓暴露的東西更加清晰并且可以節(jié)省時(shí)間去找出暴漏出來值的名字。尤其如此,在 CommonJS 中通常的實(shí)踐就是暴露一個(gè)簡(jiǎn)單的值或者對(duì)象。堅(jiān)持這種模式,可以讓我們的代碼更加可讀,并且在 ES6 和 CommonJS 模塊之間更好地兼容。
ES6 中的導(dǎo)入 在 ES6 中同樣提供了多樣的導(dǎo)入方式,我們可以這么導(dǎo)入一個(gè)整個(gè)文件:
需要著重注意的一點(diǎn)是簡(jiǎn)單的導(dǎo)入整個(gè)文件會(huì)在那個(gè)文件的頂部執(zhí)行所有的代碼
和 Python 中類似,我們可以命名導(dǎo)入的值:
import  { sumTwo, sumThree } from  'math/addition' ;
我們還可以重命名導(dǎo)入:
import  {    sumTwo as  addTwoNumbers,     sumThree as  sumThreeNumbers } from  'math/addition' ; 
另外,我們可以導(dǎo)入所有的東西(整體加載):
import  * as  util from  'math/addition' ;
最后,我們可以從一個(gè)模塊中導(dǎo)入一個(gè)值的列表:
import  * as  additionUtil from  'math/addition' ;const  { sumTwo, sumThree } = additionUtil;
可以像這樣導(dǎo)入默認(rèn)綁定的輸出:
import  api from  'math/addition' ;// Same as : import  { default as  api } from  'math/addition' ; 
雖然最好保持出口的簡(jiǎn)單,但如果需要的話我們有時(shí)可以混合默認(rèn)的進(jìn)口和混合進(jìn)口。當(dāng)我們這樣出口的時(shí)候:
// foos.js export  { foo as  default , foo1, foo2 };
我們可以這樣導(dǎo)入它們:
import  foo, { foo1, foo2 } from  'foos' ;
當(dāng)我們用 commonjs 的語法導(dǎo)入一個(gè)模塊的出口時(shí)(比如 React),我們可以這樣做:
import  React from  'react' ;const  { Component, PropTypes } = React;
還有更精簡(jiǎn)的寫法:
import  React, { Component, PropTypes } from  'react' ;
注意 :導(dǎo)出的值是動(dòng)態(tài)引用的,而不是拷貝。因此,在一個(gè)模塊中改變一個(gè)變量的綁定將影響輸出模塊中的值。應(yīng)該避免改變這些導(dǎo)出值的公共接口。(原文這里我覺得有誤)
參數(shù) 在 ES5 中,在函數(shù)中我們需要各種操作去處理 默認(rèn)參數(shù) 不定參數(shù) 重命名參數(shù) 
默認(rèn)參數(shù) function  addTwoNumbers (x, y)      x = x || 0 ;     y = y || 0 ;     return  x + y; } 
ES6 中,函數(shù)的參數(shù)可以支持設(shè)置默認(rèn)值:
function  addTwoNumbers (x=0, y=0)      return  x + y; } 
addTwoNumbers(2 , 4 ); // 6  addTwoNumbers(2 ); // 2  addTwoNumbers(); // 0  
rest 參數(shù) 在 ES5 中,我們需要這么處理不定參數(shù):
function  logArguments (    for  (var  i=0 ; i <>arguments .length; i++) {         console .log(arguments [i]);     } } 
使用 rest  ,我們就可以處理不確定數(shù)目的參數(shù):
function  logArguments (...args )      for  (let arg of args) {         console.log(arg);     } } 
命名參數(shù) 在 ES5 中是使用配置對(duì)象的模式來處理命名參數(shù),jQuery 中的使用:
function  initializeCanvas (options)      var  height = options.height || 600 ;     var  width  = options.width  || 400 ;     var  lineStroke = options.lineStroke || 'black' ; } 
我們可以利用解構(gòu)的一個(gè)函數(shù)的形參實(shí)現(xiàn)相同的功能:
function  initializeCanvas (     { height=600, width=400, lineStroke='black' })          // Use variables height, width, lineStroke here      } 
如果我們想使整個(gè)值可選擇,我們可以結(jié)構(gòu)將一個(gè)空的對(duì)象:
function  initializeCanvas (     { height=600, width=400, lineStroke='black' } = {})          // ...      } 
展開操作 在 ES5 中,我們可以 apply Math.max 方法來獲得一個(gè)數(shù)組中的最大值:
Math.max.apply(null, [-1 , 100 , 9001 , -32 ]); // 9001  
在 ES6 中,我們可以通過展開操作把一個(gè)數(shù)組的值作為參數(shù)傳遞給一個(gè)函數(shù):
Math.max(...[-1 , 100 , 9001 , -32 ]); // 9001  
我們可以更簡(jiǎn)潔地使用這個(gè)語法來合并數(shù)組:
let  cities  = ['San Francisco' , 'Los Angeles' ];let  places  = ['Miami' , ...cities , 'Chicago' ]; // ['Miami' , 'San Francisco' , 'Los Angeles' , 'Chicago' ]
類 Classes 在 ES6 之前,我們通過構(gòu)造函數(shù)來創(chuàng)造一個(gè)類,并且通過原型來擴(kuò)展屬性:
function  Person (name, age, gender)      this .name   = name;     this .age    = age;     this .gender = gender; } Person.prototype.incrementAge = function  ()       return  this .age += 1 ; }; 
然后可以這樣繼承類:
function  Personal (name, age, gender, occupation, hobby )     Person.call(this , name, age, gender);     this .occupation = occupation;     this .hobby = hobby; } Personal.prototype = Object .create(Person.prototype); Personal.prototype.constructor = Personal; Personal.prototype.incrementAge = function  (     Person.prototype.incrementAge.call(this );     this .age += 20 ;     console .log(this .age); }; 
在 ES6 中,提供了更多的語法糖,可以直接創(chuàng)造一個(gè)類:
class  Person {    constructor (name, age, gender)          this .name   = name;         this .age    = age;         this .gender = gender;     }     incrementAge() {       this .age += 1 ;     } } 
使用 extends 關(guān)鍵字來繼承一個(gè)類:
class  Personal  extends Person  {    constructor(name, age, gender, occupation, hobby) {         super (name, age, gender);         this .occupation = occupation;         this .hobby = hobby;     }     incrementAge() {         super .incrementAge();         this .age += 20 ;         console.log(this .age);     } } 
最佳實(shí)踐 :雖然使用 ES6 的語法創(chuàng)造類的時(shí)候,js引擎是如何實(shí)現(xiàn)類以及如何操作原型是令人費(fèi)解的,但是未來對(duì)初學(xué)者來說這是一個(gè)好的開始,同時(shí)也可以讓我們寫更簡(jiǎn)潔的代碼。
Symbols Symbols 在 ES6 之前就已經(jīng)存在,但是我們現(xiàn)在可以直接使用一個(gè)開發(fā)的接口了。Symbols 是不可改變并且是第一無二的,可以在任意哈希中作一個(gè)key。
Symbol() 調(diào)用 Symbol() 或者 Symbol(description) 可以創(chuàng)造一個(gè)第一無二的符號(hào),但是在全局是看不到的。Symbol() 的一個(gè)使用情況是給一個(gè)類或者命名空間打上補(bǔ)丁,但是可以確定的是你不會(huì)去更新它。比如,你想給 React.Component 類添加一個(gè) refreshComponent 方法,但是可以確定的是你不會(huì)在之后更新這個(gè)方法:
const refreshComponent = Symbol(); React.Component.prototype[refreshComponent] = ()  =>     //  do  something } 
Symbol.for(key) Symbol.for(key) 同樣會(huì)創(chuàng)造一個(gè)獨(dú)一無二并且不可改變的 Symbol,但是它可以全局看到,兩個(gè)相同的調(diào)用 Symbol.for(key) 會(huì)返回同一個(gè) Symbol 類:
Symbol ('foo' ) === Symbol ('foo' ) // false Symbol .for ('foo' ) === Symbol ('foo' ) // false Symbol .for ('foo' ) === Symbol .for ('foo' ) // true 
對(duì)于 Symbols 的普遍用法(尤其是Symbol.for(key))是為了協(xié)同性。它可以通過在一個(gè)第三方插件中已知的接口中對(duì)象中的參數(shù)中尋找用 Symbol 成員來實(shí)現(xiàn),比如:
function  reader (obj )     const  specialRead = Symbol .for('specialRead' );     if  (obj[specialRead]) {         const  reader = obj[specialRead]();         // do something with reader      } else  {         throw  new  TypeError ('object cannot be read' );     } } 
在另一個(gè)庫中:
const  specialRead = Symbol .for ('specialRead' );class  SomeReadableType      [specialRead]() {         const  reader = createSomeReaderFrom(this );         return  reader;     } } 
Maps Maps 在 JavaScript 中是一個(gè)非常必須的數(shù)據(jù)結(jié)構(gòu),在 ES6 之前,我們通過對(duì)象來實(shí)現(xiàn)哈希表:
var  map  = new  Object();map [key1] = 'value1' ;map [key2] = 'value2' ;
但是它并不能防止我們偶然地用一些特殊的屬性名重寫函數(shù):
> getOwnProperty({ hasOwnProperty : 'Hah, overwritten' }, 'Pwned' ); > TypeError : Property 'hasOwnProperty'  is  not  a function  
實(shí)際上 Maps  允許我們對(duì)值進(jìn)行 set、get 和 search 操作:
let  map  = new  Map ();> map . set ('name' , 'david' ); > map . get('name' ); // david  > map . has('name' ); // true  
Maps  更令人驚奇的部分就是它不僅限于使用字符串作為 key,還可以用其他任何類型的數(shù)據(jù)作為 key:
let  map = new  Map ([    ['name' , 'david' ],     [true , 'false' ],     [1 , 'one' ],     [{}, 'object' ],     [function  ('function' ] ]); for  (let  key of  map.keys()) {    console .log(typeof  key);     // > string, boolean, number, object, function  } 
注意 :但我們使用 map.get() 方法去測(cè)試相等時(shí),如果在 Maps 中使用 函數(shù) 或者 對(duì)象 等非原始類型值的時(shí)候測(cè)試將不起作用,所以我們應(yīng)該使用 Strings, Booleans 和 Numbers 這樣的原始類型的值。
我們還可以使用 .entries() 來遍歷迭代:
for  (let  [key, value ] of  map .entries()) {    console.log(key, value); } 
WeakMaps 在 ES6 之前,為了存儲(chǔ)私有變量,我們有各種各樣的方法去實(shí)現(xiàn),其中一種方法就是用命名約定:
class  Person {    constructor (age)          this ._age = age;     }     _incrementAge() {         this ._age += 1 ;     } } 
但是命名約定在代碼中仍然會(huì)令人混淆并且并不會(huì)真正的保持私有變量不被訪問?,F(xiàn)在,我們可以使用 WeakMaps   來存儲(chǔ)變量:
let  _age = new  WeakMap();class  Person {    constructor (age)          _age.set(this , age);     }     incrementAge() {         let  age = _age.get(this ) + 1 ;         _age.set(this , age);         if  (age > 50 ) {             console .log('Midlife crisis' );         }     } } 
在 WeakMaps 存儲(chǔ)變量很酷的一件事是它的 key 他不需要屬性名稱,可以使用 Reflect.ownKeys() 來查看這一點(diǎn):
> const  person = new  Person(50 ); > person.incrementAge(); // 'Midlife crisis'  > Reflect.ownKeys(person); // []  
一個(gè)更實(shí)際的實(shí)踐就是可以 WeakMaps 儲(chǔ)存 DOM 元素,而不會(huì)污染元素本身:
let  map  = new  WeakMap();let  el  = document. getElementById('someElement' );// Store a weak reference to the element with a key map . set (el, 'reference' );// Access the value of the element let  value = map . get(el); // 'reference' // Remove the reference el. parentNode. removeChild(el); el = null ; // map is empty, since the element is destroyed 
如上所示,當(dāng)一個(gè)對(duì)象被垃圾回收機(jī)制銷毀的時(shí)候, WeakMap 將會(huì)自動(dòng)地一處關(guān)于這個(gè)對(duì)象地鍵值對(duì)。
注意 :為了進(jìn)一步說明這個(gè)例子的實(shí)用性,可以考慮 jQuery 是如何實(shí)現(xiàn)緩存一個(gè)對(duì)象相關(guān)于對(duì)引用地 DOM 元素對(duì)象。使用 jQuery ,當(dāng)一個(gè)特定地元素一旦在 document 中移除的時(shí)候,jQuery 會(huì)自動(dòng)地釋放內(nèi)存。總體來說,jQuery 在任何 dom 庫中都是很有用的。
Promises Promises 可以讓我們遠(yuǎn)離平行的代碼(回調(diào)地獄):
func1(function  (value1 )  {     func2(value1 , function (value2 )  {         func3(value2 , function (value3 )  {             func4(value3 , function (value4 )  {                 func5(value4 , function (value5 )  {                     // Do something with value 5                  }) ;              }) ;          }) ;      }) ;  }) ;  
轉(zhuǎn)變成垂直代碼:
func1 (value 1 )     .then (func2 )     .then (func3 )     .then (func4 )     .then (func5 , value 5  => {         // Do something with value 5      }); 
在 ES6 之前,我們使用 bluebird  或者 q ,現(xiàn)在我們可以使用原生的 Promise  了。
new  Promise((resolve, reject)  =>    reject(new  Error('Failed to fulfill Promise' )))         .catch (reason => console .log(reason)); 
我們有兩個(gè)處理器,resolve(當(dāng)Promise是 fulfilled 時(shí)的回調(diào))和 reject(當(dāng)Promise是 rejected 時(shí)的回調(diào)):。
Promises的好處 :對(duì)錯(cuò)誤的處理使用一些列回調(diào)會(huì)使代碼很混亂,使用 Promise ,我看可以清晰的讓錯(cuò)誤冒泡并且在合適的時(shí)候處理它,甚至,在 Promise 確定了  resolved/rejected 之后,他的值是不可改變的--它從來不會(huì)變化。
這是使用 Promise 的一個(gè)實(shí)際的栗子:
var request = require('request ') ;  return new Promise((resolve , reject)  => {   request.get(url , (error , response, body)  => {     if (body )  {         resolve(JSON .parse(body ) ) ;        } else {         resolve({}) ;        }   }) ;  }) ;  
我們還可以使用 Promise.all() 來 并行 處理多個(gè)異步函數(shù):
let urls = [   '/api/commits' ,   '/api/issues/opened' ,   '/api/issues/assigned' ,   '/api/issues/completed' ,   '/api/issues/comments' ,   '/api/pullrequests'  ]; let promises = urls.map((url)  =>   return  new  Promise((resolve, reject)  =>     $.ajax({ url : url })       .done((data)  =>         resolve(data);       });   }); }); Promise.all(promises)   .then ((results)  =>     //  Do something with results of  all our promises  }); 
Generators 生成器 就像 Promises  可以幫我們避免回調(diào)地獄,Generators 可以幫助我們讓代碼風(fēng)格更整潔--用同步的代碼風(fēng)格來寫異步代碼,它本質(zhì)上是一個(gè)可以暫停計(jì)算并且可以隨后返回表達(dá)式的值的函數(shù)。
一個(gè)簡(jiǎn)單的栗子使用 generators:
function* sillyGenerator() {     yield  1 ;     yield  2 ;     yield  3 ;     yield  4 ; } var generator = sillyGenerator(); > console.log(generator.next ()); //  { value:  1 , done:  false  } > console.log(generator.next ()); //  { value:  2 , done:  false  } > console.log(generator.next ()); //  { value:  3 , done:  false  } > console.log(generator.next ()); //  { value:  4 , done:  false  } 
next 可以回去到下一個(gè) yield 返回的值,當(dāng)然上面的代碼是非常不自然的,我們可以利用 Generators 來用同步的方式來寫異步操作:
// Hiding asynchronousity with Generators function  request (url)      getJSON(url, function (response)           generator.next(response);     }); } 
這里的 generator 函數(shù)將會(huì)返回需要的數(shù)據(jù):
function * getData (    var  entry1 = yield  request('http://some_api/item1' );     var  data1  = JSON .parse(entry1);     var  entry2 = yield  request('http://some_api/item2' );     var  data2  = JSON .parse(entry2); } 
通過 yield,我們可以保證 entry1 有 data1 中我們需要解析并儲(chǔ)存的數(shù)據(jù)。
雖然我們可以利用 Generators 來用同步的方式來寫異步操作,但是確認(rèn)錯(cuò)誤的傳播變得不再清晰,我們可以在 Generators 中加上 Promise:
function  request (url )     return  new  Promise ((resolve, reject) => {         getJSON(url, resolve);     }); } 
然后我們寫一個(gè)函數(shù)逐步調(diào)用 next 并且利用 request 方法產(chǎn)生一個(gè) Promise:
function  iterateGenerator (gen)      var  generator = gen();     (function  iterate (val)           var  ret = generator.next();         if (!ret.done) {             ret.value.then(iterate);         }     })(); } 
在 Generators 中加上 Promise 之后我們可以更清晰的使用 Promise 中的 .catch 和 reject來捕捉錯(cuò)誤,讓我們使用新的 Generator,和之前的還是蠻相似的:
iterateGenerator(function * getData (     var  entry1 = yield  request('http://some_api/item1' );     var  data1  = JSON .parse(entry1);     var  entry2 = yield  request('http://some_api/item2' );     var  data2  = JSON .parse(entry2); }); 
Async Await 當(dāng) ES6 真正到來的時(shí)候,async await 可以用更少的處理實(shí)現(xiàn)  Promise 和  Generators 所實(shí)現(xiàn)的異步處理:
var  request = require ('request' );function  getJSON (url )   return  new  Promise (function (resolve, reject )      request(url, function (error, response, body )        resolve(body);     });   }); } async  function  main (  var  data = await  getJSON();   console .log(data); // NOT undefined!  } main(); 
在 js 引擎中,它所實(shí)現(xiàn)的和 Generators 其實(shí)是一樣的,我更推薦在 Generators + Promises 之上使用 async await,更多的資源和使用 ES7 和 用 babel 轉(zhuǎn)化可以看這里 。
Getter/Setter 函數(shù) ES6 已經(jīng)開始實(shí)現(xiàn)了 getter 和 setter 函數(shù),比如蝦面這個(gè)栗子:
class  Employee {    constructor (name)          this ._name = name;     }     get  name() {       if (this ._name) {         return  'Mr. '  + this ._name.toUpperCase();         } else  {         return  undefined ;       }       }     set  name(newName) {       if  (newName == this ._name) {         console .log('I already have this name.' );       } else  if  (newName) {         this ._name = newName;       } else  {         return  false ;       }     } } var  emp = new  Employee('James Bond' );// uses the get method in the background if  (emp.name) {  console .log(emp.name);  // Mr. JAMES BOND  } // uses the setter in the background emp.name = 'Bond 007' ; console .log(emp.name);  // Mr. BOND 007 
最新版本的瀏覽器也在對(duì)象中實(shí)現(xiàn)了 getter 和 setter 函數(shù),我們可以使用它們來實(shí)現(xiàn) 計(jì)算屬性 ,在設(shè)置和獲取一個(gè)屬性之前加上監(jiān)聽器和處理。
var  person = {  firstName: 'James' ,   lastName: 'Bond' ,   get  fullName (       console.log('Getting FullName' );       return  this .firstName + ' '  + this .lastName;   },   set  fullName  (name )        console.log('Setting FullName' );       var  words = name.toString().split(' ' );       this .firstName = words[0 ] || '' ;       this .lastName = words[1 ] || '' ;   } } person.fullName; // James Bond  person.fullName = 'Bond 007' ; person.fullName; // Bond 007