隨著React的風靡,配合Webpack以及Babel等技術,越來越多的前端同學將ECMAScript 2015(ES6)的特性運用在專案中,import、export、class、箭頭函式、塊級作用域等特性屢試不爽。而對於Node.js實現的後臺程式碼來說,我們也同樣希望使用這些ES6特性,下面將以v4.4.4(LTS version)長期支援版本為例展開話題,從相容性以及效能兩方面著手分析Node.js對ES6的支援情況。
相容性
隨著io.js的引入,新版的Node.js開始原生支援部分ES6的特性,既然ES6在瀏覽器端使用需要通過babel等編譯,在Node.js總可以放心使用了吧,然而事實並非如此。
所有的ES6特性被劃分為三個級別:
- shipping:已經分發並預設開啟的特性;
- staged:已經分發,但需要使用 –harmony 引數開啟的特性;
- in progress:開發中,還不穩定或者未實現的特性,不推薦使用;
Nodejs各個版本對ES6特性的相容列表見:http://node.green/
【shipping】
ES6特性 | Nodejs相容性 |
---|---|
let,const,塊 | strict模式支援 |
class類 | strict模式支援 |
Map,Set 和 WeakMap,WeakSet | 支援 |
generators | 支援 |
進位制轉換 | 支援 |
物件字面量擴充套件 | 支援 |
promise | 支援 |
String物件新API | 支援 |
symbols | 支援 |
字串模板 | 支援 |
這些都是Node.js原生支援的特性,除了前兩個特性需要在程式碼前面新增’use strict’。
【staged】
- Symbol.toStringTag
- Array.prototype.includes
- Rest Parameters
- ……
可通過node –v8-options | findstr harmony進行檢視。在執行帶有這些特性的js程式碼時,需要加上–harmony引數,例如:node –harmony app.js。
【in progress】
- harmony_modules (enable “harmony modules”)
- harmonyarrayincludes (enable “harmony Array.prototype.includes”)
- harmony_regexps (enable “harmony regular expression extensions”)
- harmonynewtarget (enable “harmony new.target”)
- ……
可通過node –v8-options | findstr “in progress”進行檢視。這些特性是那些將要支援(但具體時間未知)的特性,不建議使用。
Node.js 6.x 已經支援 93% 的ES6特性
從上面分析可以看到,Node.js 4.x版本對ES6特性的原生支援並不好,但是好訊息是,Node.js 6.x LTS version將要釋出了,帶來了效能的大幅提升、更好的測試、更完善的文件、更好的安全性,並廣泛支援了ES6。
在 Node.js 5.0 釋出了6個月以後,6.0的時代馬上就來了,目標是替換 4.x,計劃在2016年10月成為下一個LTS version(長期支援的版本),5.0 只是一個過渡版本。考慮到產品的穩定性,建議大家目前還是繼續使用 Node.js 4.x,直到10月份。
Node.js 6.x 的一項重要改進是使用了V8 5.0引擎,支援了93%以上的ES6,包括 destructuring、rest 引數、class和super關鍵字,ES6還沒有被覆蓋到的只剩下一小部分,包括 direct、mutual recursion、iterator closing 等。
讓我們一起期待吧!
效能
ES6是大勢所趨,儘管目前Node下使用ES6仍然存在很多問題,這裡還是有必要對ES6的原生效能做一下對比測試,好讓大家有個量化的概念。
環境描述:
CPU:Intel(R) Core(TM)i7-4790 CPU @ 3.60GHz
RAM:16.0GB
作業系統:64bit
node版本:v4.4.4
1.塊級作用域
測試程式碼如下:
ES5:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var i = 0; var start = +new Date(), duration; while(i++ < 1000000){ var a = 1; var b = '1'; var c = true; var d = {}; var e = []; } duration = +new Date() - start; console.log(duration); |
輸出結果為45ms。
ES6:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
'use strict' let i = 0; let start = +new Date(), duration; while(i++ < 1000000){ const a = 1; const b = '1'; const c = true; const d = {}; const e = []; } duration = +new Date() - start; console.log(duration); |
輸出結果為29ms。
可見,使用let,const宣告變數的速度比var快了約55%左右。
2.class
測試程式碼如下:
ES5:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
var i = 0; var start = +new Date(), duration; function A(){ this.name = '小強'; } A.prototype.getName = function() { return this.name; }; while(i++ < 100000){ var a = new A(); a.getName(); } duration = +new Date() - start; console.log(duration); |
輸出結果為2ms。
ES6:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
'use strict' let i = 0; let start = +new Date(), duration; class A{ constructor() { this.name = '小強'; } getName(){ return this.name; } } while(i++ < 100000){ const a = new A(); a.getName(); } duration = +new Date() - start; console.log(duration); |
輸出結果為974ms。
可見,class沒有絲毫優勢,function真是快的不得了。
3.Map
測試程式碼如下:
ES5:
1 2 3 4 5 6 7 8 9 10 11 |
var i = 0; var start = +new Date(), duration; while(i++ < 1000000){ var map = {}; map['key'] = 'value'; } duration = +new Date() - start; console.log(duration); |
輸出結果為11ms。
ES6:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
'use strict' let i = 0; let start = +new Date(), duration; while(i++ < 1000000){ let map = new Map(); map.set('key','value'); } duration = +new Date() - start; console.log(duration); |
輸出結果為151ms。
建議如果不是必須情況,不要使用Map等複雜型別。
4.字串模板
測試程式碼如下:
ES5:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
var i = 0; var start = +new Date(), duration; var vars = { name: 'haha', address: 'tencent' } while(i++ < 1000000){ var str = 'string text ' + vars.name + 'string '+ vars.address; } duration = +new Date() - start; console.log(duration); |
輸出結果為8ms。
ES6:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
'use strict' let i = 0; let start = +new Date(), duration; let vars = { name: 'haha', address: 'tencent' }; while(i++ < 1000000){ let str = `string text ${vars.name} string ${vars.address}`; } duration = +new Date() - start; console.log(duration); |
輸出結果為50ms。
字串模板在執行時由於會首先找出其中的模板變數,所以效能也是大不如ES5的字串拼接。
其他特性有興趣的同學可以一一做測試。
總結
對於ES6來說,我們不僅要了解其特性的相容性,也要從效能上做到心中有數,從上面的測試結果可以看到,大部分ES6新特性相對ES5原生方法要慢得多,但是我依然堅信,ES6是未來的趨勢,隨著Node版本的更新,相信這些相容性以及效能問題在不久的將來都將迎刃而解。