ES6中比較實用的幾個特性


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 classicalclassicalfunctional 更加增加了混亂,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)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM