1.Default Parameters(默認參數) in ES6
es6之前,定義默認參數的方法是在一個方法內部定義
1 var link = function (height, color, url) { 2 var height = height || 50; 3 var color = color || 'red'; 4 var url = url || 'http://azat.co'; 5 ... 6 }
es6寫法,簡單粗暴了很多了
var link = function(height = 50, color = 'red', url = 'http://azat.co') { ... }
2.Template Literals(模板對象) in ES6
es6之前定義模版字符串要這樣寫,其中first和last 是變量
1 var name = 'Your name is ' + first + ' ' + last + '.'; 2 var url = 'http://localhost:3000/api/messages/' + id;
es6中使用新的語法${ },就簡單多啦,注意es6中的模版字符串用得是反引號``
var name = `Your name is ${first} ${last}. `; var url = `http://localhost:3000/api/messages/${id}`;
3.Multi-line Strings (多行字符串)in ES6
es6之前定義多行字符串要這樣寫
1 var roadPoem = 'Then took the other, as just as fair,nt' 2 + 'And having perhaps the better claimnt' 3 + 'Because it was grassy and wanted wear,nt' 4 + 'Though as for that the passing therent' 5 + 'Had worn them really about the same,nt'; 6 var fourAgreements = 'You have the right to be you.n 7 You can only be you when you do your best.';
es6中的模版字符串也可以輕松實現,甚至插入變量也變得非常簡單
1 var roadPoem = `Then took the other, as just as fair, 2 And having perhaps the better claim 3 Because it was grassy and wanted wear, 4 Though as for that the passing there 5 Had worn them really about the same,`; 6 var fourAgreements = `You have the right to be you. 7 You can only be you when you do your best.`;
4.Destructuring Assignment (解構賦值)in ES6
在es5中是這樣寫的
1 var data = $('body').data(), // data has properties house and mouse 2 house = data.house, 3 mouse = data.mouse;
在nodejs中是這樣的
1 var jsonMiddleware = require('body-parser').jsonMiddleware ; 2 var body = req.body, // body has username and password 3 username = body.username, 4 password = body.password;
在es6中就簡化了很多
1 var { house, mouse} = $('body').data(); // we'll get house and mouse variables 2 var {jsonMiddleware} = require('body-parser'); 3 var {username, password} = req.body;
同樣適用於數組
1 var [col1, col2] = $('.column'), 2 [line1, line2, line3, , line5] = file.split('n');
5.Enhanced Object Literals (增強的對象字面量)in ES6
一個典型ES5對象文本,里面有一些方法和屬性
1 var serviceBase = {port: 3000, url: 'azat.co'}, 2 getAccounts = function(){return [1,2,3]}; 3 var accountServiceES5 = { 4 port: serviceBase.port, 5 url: serviceBase.url, 6 getAccounts: getAccounts, 7 toString: function() { 8 return JSON.stringify(this.valueOf()); 9 }, 10 getUrl: function() {return "http://" + this.url + ':' + this.port}, 11 valueOf_1_2_3: getAccounts() 12 }
我們想讓它更有意思,我們可以用Object.create從serviceBase繼承原型的方法:
1 var accountServiceES5ObjectCreate = Object.create(serviceBase) 2 var accountServiceES5ObjectCreate = { 3 getAccounts: getAccounts, 4 toString: function() { 5 return JSON.stringify(this.valueOf()); 6 }, 7 getUrl: function() {return "http://" + this.url + ':' + this.port}, 8 valueOf_1_2_3: getAccounts() 9 }
在ES6的對象文本中,既可以直接分配getAccounts: getAccounts,也可以只需用一個getAccounts,此外,我們在這里通過__proto__(並不是通過’proto’)設置屬性,如下所示:
1 var serviceBase = {port: 3000, url: 'azat.co'}, 2 getAccounts = function(){return [1,2,3]}; 3 var accountService = { 4 __proto__: serviceBase, 5 getAccounts, 6 toString() { 7 return JSON.stringify((super.valueOf())); 8 }, 9 getUrl() {return "http://" + this.url + ':' + this.port}, 10 [ 'valueOf_' + getAccounts().join('_') ]: getAccounts() 11 }; 12 console.log(accountService)
ES6對象文本對於舊版的對象文本來說是一個很大的進步。
6.Arrow Functions in(箭頭函數) ES6、
在ES6中,有了豐富的箭頭函數。這些豐富的箭頭是令人驚訝的因為它們將使許多操作變成現實,比如,以前我們使用閉包,this總是預期之外地產生改變,而箭頭函數的迷人之處在於,現在你的this可以按照你的預期使用了,身處箭頭函數里面,this還是原來的this。有了箭頭函數在ES6中, 我們就不必用that = this或 self = this 或 _this = this 或.bind(this)。例如,下面的代碼用ES5就不是很優雅:
1 var _this = this; 2 $('.btn').click(function(event){ 3 _this.sendData(); 4 })
在ES6中就不需要用 _this = this:
1 $('.btn').click((event) =>{ 2 this.sendData(); 3 })
一個另外的例子,我們通過call傳遞文本給logUpperCase() 函數在ES5中:
1 var logUpperCase = function() { 2 var _this = this; 3 4 this.string = this.string.toUpperCase(); 5 return function () { 6 return console.log(_this.string); 7 } 8 } 9 10 logUpperCase.call({ string: 'ES6 rocks' })();
而在ES6,我們並不需要用_this浪費時間:
1 var logUpperCase = function() { 2 this.string = this.string.toUpperCase(); 3 return () => console.log(this.string); 4 } 5 logUpperCase.call({ string: 'ES6 rocks' })();
請注意,只要你願意,在ES6中=>可以混合和匹配老的函數一起使用。當在一行代碼中用了箭頭函數,它就變成了一個表達式。它將暗地里返回單個語句的結果。如果你超過了一行,將需要明確使用return。
這是用ES5代碼創建一個消息數組:
1 var ids = ['5632953c4e345e145fdf2df8','563295464e345e145fdf2df9']; 2 var messages = ids.map(function (value) { 3 return "ID is " + value; // explicit return 4 });
ES6是這樣:
1 var ids = ['5632953c4e345e145fdf2df8','563295464e345e145fdf2df9']; 2 var messages = ids.map(value => `ID is ${value}`); // implicit return
請注意,這里用了字符串模板。在箭頭函數中,對於單個參數,括號()是可選的,但當你超過一個參數的時候你就需要他們。在ES5代碼有明確的返回功能:
1 var ids = ['5632953c4e345e145fdf2df8', '563295464e345e145fdf2df9']; 2 var messages = ids.map(function (value, index, list) { 3 return 'ID of ' + index + ' element is ' + value + ' '; // explicit return 4 });
在ES6中有更加嚴謹的版本,參數需要被包含在括號里並且它是隱式的返回:
1 var ids = ['5632953c4e345e145fdf2df8','563295464e345e145fdf2df9']; 2 var messages = ids.map((value, index, list) => `ID of ${index} element is ${value} `); // implicit return
7. Promises in ES6,
es6中極為強大的promise
Promises 是一個有爭議的話題。因此有許多略微不同的promise 實現語法。Q,bluebird,deferred.js,vow, avow, jquery 一些可以列出名字的。也有人說我們不需要promises,僅僅使用異步,生成器,回調等就夠了。但令人高興的是,在ES6中有標准的Promise實現。
下面是一個簡單的用setTimeout()實現的異步延遲加載函數:
1 setTimeout(function(){ 2 console.log('Yay!'); 3 }, 1000);
在ES6中,我們可以用promise重寫:
1 var wait1000 = new Promise(function(resolve, reject) { 2 setTimeout(resolve, 1000); 3 }).then(function() { 4 console.log('Yay!'); 5 });
或者用ES6的箭頭函數:
1 var wait1000 = new Promise((resolve, reject)=> { 2 setTimeout(resolve, 1000); 3 }).then(()=> { 4 console.log('Yay!'); 5 });
有人會說:脫褲子放屁,多此一舉嘛!
但是:如果我們有更多的嵌套邏輯在setTimeout()回調函數中,我們將發現更多好處:
1 setTimeout(function(){ 2 console.log('Yay!'); 3 setTimeout(function(){ 4 console.log('Wheeyee!'); 5 }, 1000) 6 }, 1000);
在ES6中我們可以用promises重寫:
1 var wait1000 = ()=> new Promise((resolve, reject)=> {setTimeout(resolve, 1000)}); 2 wait1000() 3 .then(function() { 4 console.log('Yay!') 5 return wait1000() 6 }) 7 .then(function() { 8 console.log('Wheeyee!') 9 });
這種寫法,方法的執行順序和嵌套關系清晰明了,如果有多層嵌套,那你懂的!
8.Block-Scoped Constructs Let and Const(塊作用域和構造let和const)
在ES6代碼中,你可能已經看到那熟悉的身影let。在ES6里let並不是一個花俏的特性,它是更復雜的。Let是一種新的變量申明方式,它允許你把變量作用域控制在塊級里面。我們用大括號定義代碼塊,在ES5中,塊級作用域起不了任何作用:
1 function calculateTotalAmount (vip) { 2 var amount = 0; 3 if (vip) { 4 var amount = 1; 5 } 6 { // more crazy blocks! 7 var amount = 100; 8 { 9 var amount = 1000; 10 } 11 } 12 return amount; 13 } 14 console.log(calculateTotalAmount(true)); //輸出1000
結果將返回1000,這真是一個bug。在ES6中,我們用let限制塊級作用域。而var是限制函數作用域。
function calculateTotalAmount (vip) { var amount = 0; // probably should also be let, but you can mix var and let if (vip) { let amount = 1; // first amount is still 0 } { // more crazy blocks! let amount = 100; // first amount is still 0 { let amount = 1000; // first amount is still 0 } } return amount; } console.log(calculateTotalAmount(true)); //0
9. Classes (類)in ES6
如果你喜歡面向對象編程(OOP),那么你將喜愛這個特性。以后寫一個類和繼承將變得容易。類的創建和使用真是一件令人頭疼的事情在過去的ES5中,因為沒有一個關鍵字class (它被保留,但是什么也不能做)。在此之上,大量的繼承模型像pseudo classical, classical, functional 更加增加了混亂,JavaScript 之間的宗教戰爭只會更加火上澆油。用ES5寫一個類,有很多種方法,這里就先不說了。現在就來看看如何用ES6寫一個類吧。ES6沒有用函數, 而是使用原型實現類。我們創建一個類baseModel ,並且在這個類里定義了一個constructor 和一個 getName()方法:
1 class baseModel { 2 constructor(options, data) { // class constructor,node.js 5.6暫時不支持options = {}, data = []這樣傳參 3 this.name = 'Base'; 4 this.url = 'http://azat.co/api'; 5 this.data = data; 6 this.options = options; 7 } 8 9 getName() { // class method 10 console.log(`Class name: ${this.name}`); 11 } 12 }
注意我們對options 和data使用了默認參數值。此外方法名也不需要加function關鍵字,而且冒號(:)也不需要了。另外一個大的區別就是你不需要分配屬性this。現在設置一個屬性的值,只需簡單的在構造函數中分配。
AccountModel 從類baseModel 中繼承而來:
1 class AccountModel extends baseModel { 2 constructor(options, data) { 3 super({private: true}, ['32113123123', '524214691']); 4 this.name = 'Account Model'; 5 this.url +='/accounts/'; 6 } 7 get accountsData() { //calculated attribute getter 8 // ... make XHR 9 return this.data; 10 } 11 }
那么,你如何調用他們呢?它是非常容易的:
1 let accounts = new AccountModel(5); 2 accounts.getName(); 3 console.log('Data is %s', accounts.accountsData);
結果令人驚訝,輸出是:Class name: Account Model Data is 32113123123,524214691
10. Modules (模塊)in ES6
眾所周知,在ES6以前JavaScript並不支持本地的模塊。人們想出了AMD,RequireJS,CommonJS以及其它解決方法。現在ES6中可以用模塊import 和export 操作了。在ES5中,你可以在 <script>中直接寫可以運行的代碼(簡稱IIFE),或者一些庫像AMD。然而在ES6中,你可以用export導入你的類。下面舉個例子,在ES5中,module.js有port變量和getAccounts 方法:
1 module.exports = { 2 port: 3000, 3 getAccounts: function() { 4 ... 5 } 6 }
在ES5中,main.js需要依賴require(‘module’) 導入module.js:
1 var service = require('module.js'); 2 console.log(service.port); // 3000
但在ES6中,我們將用export and import。例如,這是我們用ES6 寫的module.js文件庫:
1 export var port = 3000; 2 export function getAccounts(url) { 3 ... 4 }
如果用ES6來導入到文件main.js中,我們需用import {name} from ‘my-module’語法,例如:
1 import {port, getAccounts} from 'module'; 2 console.log(port); // 3000
或者我們可以在main.js中把整個模塊導入, 並命名為 service:
1 import * as service from 'module'; 2 console.log(service.port); // 3000
這里還有許多ES6的其它特性你可能會使用到,排名不分先后:
1、全新的Math, Number, String, Array 和 Object 方法
2、二進制和八進制數據類型
3、默認參數不定參數擴展運算符
4、Symbols符號
5、tail調用
6、Generators (生成器)
7、New data structures like Map and Set(新的數據構造對像MAP和set)