本文標題有誤導性,因為我其實想寫node8的新特性,說實話一下子從node v1.x跳躍到node 8.x+ 真有點受寵若驚的感覺。愛掏網 - it200.com一直覺得node 數組、 對象、序列等的處理沒有python方便,因為需要借助外部的一些包比如underscore /lodash才能實現,但是接下來是見證奇跡的時刻,es6/7/8讓node代碼變的更簡潔、更易懂。愛掏網 - it200.com
Node.js的優點之一就是前后端用同一種語言,本質上還是js,因此可以通過babel來使nodejs支持對應的ECMAScript。愛掏網 - it200.com
目錄
- 如何讓Nodejs支持對應的ES
-
ES6常用新特性
- let && const
- iterable類型
- 解構賦值
- =>函數
- ...操作符
- 類
-
ES7新特性
- Array.prototype.includes
- Exponentiation Operator(求冪運算)
-
ES8新特性
- Object.values/Object.entries
- String padding(字符串填充)
- Object.getOwnPropertyDescriptors
- 函數參數列表和調用中的尾逗號(Trailing commas)
- 異步函數(Async Functions)
如何讓Nodejs支持對應的ES
不同版本的Node.js對Babel有不同的支持,如若是Nodejs支持ES6語法,需要引入babel。愛掏網 - it200.com因此要安裝一些babel的依賴包,如babel-preset-es2024 / babel-core /babel-cli。愛掏網 - it200.com
ES6對應es2024,ES7對應es2024,ES8對應es2024,同時對應支持的node版本更高。愛掏網 - it200.com
檢測ES6
可以使用es-checker來檢測當前Node.js對ES6的支持情況,全局安裝es-checker
$ npm install -g es-checker
安裝好之后,執行以下命令來查看Node.js對ES6的支持情況:
$ es-checker
可以從輸出中查看當前版本Node.js(v7.7.4)對ES6的支持情況:

$ es-checker ECMAScript 6 Feature Detection (v1.4.1) Variables √ let and const √ TDZ error for too-early access of let or const declarations √ Redefinition of const declarations not allowed √ destructuring assignments/declarations for arrays and objects √ ... operator Data Types √ For...of loop √ Map, Set, WeakMap, WeakSet √ Symbol √ Symbols cannot be implicitly coerced Number √ Octal (e.g. 0o1 ) and binary (e.g. 0b10 ) literal forms √ Old octal literal invalid now (e.g. 01 ) √ Static functions added to Math (e.g. Math.hypot(), Math.acosh(), Math.imul() ) √ Static functions added to Number (Number.isNaN(), Number.isInteger() ) String √ Methods added to String.prototype (String.prototype.includes(), String.prototype.repeat() ) √ Unicode code-point escape form in string literals (e.g. \u{20BB7} ) √ Unicode code-point escape form in identifier names (e.g. var \u{20BB7} = 42; ) √ Unicode code-point escape form in regular expressions (e.g. var regexp = /\u{20BB7}/u; ) √ y flag for sticky regular expressions (e.g. /b/y ) √ Template String Literals Function √ arrow function √ default function parameter values √ destructuring for function parameters √ Inferences for function name property for anonymous functions × Tail-call optimization for function calls and recursion Array × Methods added to Array.prototype ([].fill(), [].find(), [].findIndex(), [].entries(), [].keys(), [].values() ) √ Static functions added to Array (Array.from(), Array.of() ) √ TypedArrays like Uint8Array, ArrayBuffer, Int8Array(), Int32Array(), Float64Array() √ Some Array methods (e.g. Int8Array.prototype.slice(), Int8Array.prototype.join(), Int8Array.prototype.forEach() ) added to the TypedArray prototypes √ Some Array statics (e.g. Uint32Array.from(), Uint32Array.of() ) added to the TypedArray constructors Object √ __proto__ in object literal definition sets [[Prototype]] link √ Static functions added to Object (Object.getOwnPropertySymbols(), Object.assign() ) √ Object Literal Computed Property √ Object Literal Property Shorthands √ Proxies √ Reflect Generator and Promise √ Generator function √ Promises Class √ Class √ super allowed in object methods √ class ABC extends Array { .. } Module × Module export command × Module import command ========================================= Passes 38 feature Detections Your runtime supports 90% of ECMAScript 6 =========================================View Code
添加es6支持
全局安裝babel-cli, 項目安裝 babel-preset-es2024:
npm install babel-cli -g
npm install babel-preset-es2024 --save
安裝完之后,還需要添加一個名為.babelrc的配置文件。愛掏網 - it200.com方便babel-cli使用babel-preset-es2024。愛掏網 - it200.com文件內容如下:
{
"presets": ["es2024"],
"plugins": [
"add-module-exports"
]
}
或者在項目入口文件(如app.js)引用下babel:
require('babel-register')({
presets: ['es2024']
});
如此,再也不會報如下的錯誤:
import a from './config';
^^^^^^
SyntaxError: Unexpected token import
并且也會支持ES6的新特性。愛掏網 - it200.com上述是描述node如何支持ES6的,支持ES8是類似的,preset指定?"presets": ["es2024"]即可。愛掏網 - it200.com
下面進入正題,到底ES6~8有哪些實用的新特性呢
ES6常用新特性
let && const?
let 命令也用于變量聲明,但是作用域為局部
{ let a = 10; var b = 1; }
在函數外部可以獲取到b,獲取不到a,因此例如for循環計數器就適合使用let。愛掏網 - it200.com
const用于聲明一個常量,設定后值不會再改變
const PI = 3.1415; PI // 3.1415 PI = 3; //TypeError: Assignment to constant variable.
iterable類型
為了統一集合類型,ES6標準引入了新的iterable類型,Array、Map和Set都屬于iterable類型,具有iterable類型的集合可以通過新的for … of循環來遍歷。愛掏網 - it200.com
var a = ['A', 'B', 'C']; var s = new Set(['A', 'B', 'C']); var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]); for (var x of a) { // 遍歷Array alert(x); } for (var x of s) { // 遍歷Set alert(x); } for (var x of m) { // 遍歷Map alert(x[0] + '=' + x[1]); }
Map相關操作如下, Set同理:
var m = new Map(); // 空Map m.set('Adam', 67); // 添加新的key-value m.set('Bob', 59); m.has('Adam'); // 是否存在key 'Adam': true m.get('Adam'); // 67 m.delete('Adam'); // 刪除key 'Adam' m.get('Adam'); // undefined
解構賦值
ES6 允許按照一定模式,從數組和對象中提取值,對變量進行賦值,這被稱為解構(Destructuring)。愛掏網 - it200.com?
例如數組:
let [a, b, c] = [1, 2, 3]; //等同于 let a = 1; let b = 2; let c = 3;
這真的讓代碼看起來更優美,有種python賦值的既視感。愛掏網 - it200.com?
對象的解構賦值:獲取對象的多個屬性并且使用一條語句將它們賦給多個變量。愛掏網 - it200.com
var { StyleSheet, Text, View } = React; 等同于 var StyleSheet = React.StyleSheet; var Text = React.Text; var View = React.Text;
箭頭函數
ES6中新增箭頭操作符用于簡化函數的寫法,操作符左邊為參數,右邊為具體操作和返回值。愛掏網 - it200.com
var sum = (num1, num2) => { return num1 + num2; } //等同于 var sum = function(num1, num2) { return num1 + num2; };
箭頭函數還修復了this的指向,使其永遠指向詞法作用域:
var obj = { birth: 1990, getAge: function () { var b = this.birth; // 1990 var fn = () => new Date().getFullYear() - this.birth; // this指向obj對象 return fn(); } }; obj.getAge(); // 25
...操作符
這個的引入幾乎不會用到extend這個函數來。愛掏網 - it200.com通過它可以將數組作為參數直接傳入函數:
var people=['Wayou','John','Sherlock']; function sayHello(people1,people2,people3){ console.log(`Hello ${people1},${people2},${people3}`); } //改寫為 sayHello(...people);//輸出:Hello Wayou,John,Sherlock
在函數定義時可以通過…rest獲取定義參數外的所有參數(類似C#中的參數數組,可以有任意多個參數):
function foo(a, b, ...rest) { console.log('a = ' + a); console.log('b = ' + b); console.log(rest); } foo(1, 2, 3, 4, 5); // 結果: // a = 1 // b = 2 // Array [ 3, 4, 5 ]
這個真是完美!關于更多...的說明參考這篇博客
類
ES6提供了更接近傳統語言的寫法,引入了Class(類)這個概念,作為對象的模板。愛掏網 - it200.com通過class關鍵字,可以定義類,與多數傳統語言類似。愛掏網 - it200.com
//定義類 class Point { constructor(x, y) { this.x = x; this.y = y; } toString() { return '(' + this.x + ', ' + this.y + ')'; } }
ES7新特性
Array.prototype.includes
Array.prototype.includes用法都容易和簡單。愛掏網 - it200.com它是一個替代indexOf,開發人員用來檢查數組中是否存在值,indexOf是一種尷尬的使用,因為它返回一個元素在數組中的位置或者-1當這樣的元素不能被找到的情況下。愛掏網 - it200.com所以它返回一個數字,而不是一個布爾值。愛掏網 - it200.com開發人員需要實施額外的檢查。愛掏網 - it200.com在ES6,要檢查是否存在值你需要做一些如下圖所示小技巧,因為他們沒有匹配到值,Array.prototype.indexOf返回-1變成了true(轉換成true),但是當匹配的元素為0位置時候,該數組包含元素,卻變成了false。愛掏網 - it200.comlet arr = ['react', 'angular', 'vue'] // WRONG if (arr.indexOf('react')) { // 0 -> evaluates to false, definitely as we expected console.log('Can use React') // this line would never be executed } // Correct if (arr.indexOf('react') !== -1) { console.log('Can use React') }
或者使用一點點hack 位運算符?~
?使代碼更加緊湊一些,因為~
(位異或)對任何數字相當于-(a + 1)
:
let arr = ['react', 'angular', 'vue'] // Correct if (~arr.indexOf('react')) { console.log('Can use React') }
在ES7中使用includes
代碼如下:
let arr = ['react', 'angular', 'vue'] // Correct if (arr.includes('react')) { console.log('Can use React') }
還能在字符串中使用includes
:
let str = 'React Quickly' // Correct if (str.toLowerCase().includes('react')) { // true console.log('Found "react"') }
除了增強了可讀性語義化,實際上給開發者返回布爾值,而不是匹配的位置。愛掏網 - it200.com
includes
也可以在NaN
(非數字)使用。愛掏網 - it200.com最后 ,includes
第二可選參數fromIndex
,這對于優化是有好處的,因為它允許從特定位置開始尋找匹配。愛掏網 - it200.com
更多例子:
console.log([1, 2, 3].includes(2)) // === true) console.log([1, 2, 3].includes(4)) // === false) console.log([1, 2, NaN].includes(NaN)) // === true) console.log([1, 2, -0].includes(+0)) // === true) console.log([1, 2, +0].includes(-0)) // === true) console.log(['a', 'b', 'c'].includes('a')) // === true) console.log(['a', 'b', 'c'].includes('a', 1)) // === false)
總而言之,includes在一個數組或者列表中檢查是否存在一個值,給任何開發人員帶來簡單性。愛掏網 - it200.com
Exponentiation Operator(求冪運算)
求冪運算大多數是做一些數學計算,對于3D,VR,SVG還有數據可視化非常有用。愛掏網 - it200.com在ES6或者早些版本,不得不創建一個循環,創建一個遞歸函數或者使用Math.pow
,如果忘記了什么是指數,當你有相同數字(基數)自相相乘多次(指數)。愛掏網 - it200.com例如,7的3次方是7*7*7
所以在ES6/2024ES,你能使用Math.pow
創建一個短的遞歸箭頭函數:
calculateExponent = (base, exponent) => base*((--exponent>1)?calculateExponent(base, exponent):base) console.log(calculateExponent(7,12) === Math.pow(7,12)) // true console.log(calculateExponent(2,7) === Math.pow(2,7)) // true
現在在ES7 /ES2024,以數學向導的開發者可以使用更短的語法:
let a = 7 ** 12 let b = 2 ** 7 console.log(a === Math.pow(7,12)) // true console.log(b === Math.pow(2,7)) // true
開發者還可以操作結果:
let a = 7 a **= 12 let b = 2 b **= 7 console.log(a === Math.pow(7,12)) // true console.log(b === Math.pow(2,7)) // true
許多ES新特性是從其他語言(CoffeeScript,Ruby,python等)模仿而來的
ES8新特性
Object.values/Object.entries
Object.values
和?Object.entries
是在ES2024規格中,它和Object.keys
類似,返回數組類型,其序號和Object.keys
序號對應。愛掏網 - it200.com類似python中的dict.iteritems()。愛掏網 - it200.com
Object.values
,Object.entries
和Object.keys
各自項返回是數組,相對應包括key,value或者可枚舉特定對象property/attribute
在ES8 /ES2024之前,Javascript開發者需要迭代一個對象的自身屬性時候不得不用Object.keys
,通過迭代且使用obj[key]
獲取value值返回一個數組,很挫的:
let obj = {a: 1, b: 2, c: 3} Object.keys(obj).forEach((key, index)=>{ console.log(key, obj[key]) })
而使用ES6/ES2024 中for/of
稍微好點:
let obj = {a: 1, b: 2, c: 3} for (let key of Object.keys(obj)) { console.log(key, obj[key]) }
Object.values
返回對象自身可以迭代屬性值(values)為數組類型。愛掏網 - it200.com我們最好使用Array.prototype.forEach
迭代它,結合ES6的箭頭函數隱形返回值:
let obj = {a: 1, b: 2, c: 3} Object.values(obj).forEach(value=>console.log(value)) // 1, 2, 3
或者實用for/of:
let obj = {a: 1, b: 2, c: 3} for (let value of Object.values(obj)) { console.log(value) } // 1, 2, 3
·Object.entries·,在另一方面,將會返回對象自身可迭代屬性key-value對數組(作為一個數組),他們(key-value)分別以數組存放數組中:
let obj = {a: 1, b: 2, c: 3}
JSON.stringify(Object.entries(obj))
"[["a",1],["b",2],["c",3]]"
可以使用ES6/ES2024解構,從這嵌套數組中分別聲明key和value
let obj = {a: 1, b: 2, c: 3} Object.entries(obj).forEach(([key, value]) => { console.log(`${key} is ${value}`) }) // a is 1, b is 2, c is 3
同樣使用ES6for/of
(畢竟全部都是數組)遍歷Object.entries
返回來的結果值:
let obj = {a: 1, b: 2, c: 3} for (let [key, value] of Object.entries(obj)) { console.log(`${key} is ${value}`) } // a is 1, b is 2, c is 3
現在從對象中提取values和key-value pairs 變得非常容易了。愛掏網 - it200.comObject.values
和Object.entries
這種方式不想之前?Object.keys
(自身屬性key+順序相同)結合for/of
(ES6)一起,我們不僅僅可以提取他們還可以迭代他們。愛掏網 - it200.com
String padding(字符串填充)
String.prototype.padStart
和 String.prototype.padEnd
在javascript字符操作是一個不錯的體驗,幫助避免依賴而外的庫。愛掏網 - it200.compadStart()
在開始部位填充,返回一個給出長度的字符串,填充物給定字符串,把字符串填充到期望的長度。愛掏網 - it200.com從字符串的左邊開始(至少大部分西方語言),一個經典例子是使用空格創建列:
console.log('react'.padStart(10).length) // " react" is 10 console.log('backbone'.padStart(10).length) // " backbone" is 10
它對于財務方面非常有用:
console.log('0.00'.padStart(20)) console.log('10,000.00'.padStart(20)) console.log('250,000.00'.padStart(20))
如果是為會計做賬之類的,這個很實用,帳做的很整齊
0.00 10,000.00 250,000.00
第二個參數,讓我們放一些其他的填充字符替代空字符串,一個字符串填充:
console.log('react'.padStart(10, '_')) // "_____react" console.log('backbone'.padStart(10, '*')) // "**backbone"
padEnd
顧名思義就是從字符串的尾端右邊開始填充。愛掏網 - it200.com第二個參數,你能實際上用一個任何長度的字符串。愛掏網 - it200.com例如:
console.log('react'.padEnd(10, ':-)')) // "react:-):-" is 10 console.log('backbone'.padEnd(10, '*')) // "backbone**" is 10
再賞幾個例子作為總結:
// String.prototype.padStart(targetLength [, padString]) 'hello'.padStart(10); // ' hello' 'hello'.padStart(10, '0'); // '00000hello' 'hello'.padStart(); // 'hello' 'hello'.padStart(6, '123'); // '1hello' 'hello'.padStart(3); // 'hello' 'hello'.padStart(3, '123'); // 'hello'; // String.prototype.padEnd(targetLength [, padString]) 'hello'.padEnd(10); // 'hello ' 'hello'.padEnd(10, '0'); // 'hello00000' 'hello'.padEnd(); // 'hello' 'hello'.padEnd(6, '123'); // 'hello1' 'hello'.padEnd(3); // 'hello' 'hello'.padEnd(3, '123'); // 'hello';
Object.getOwnPropertyDescriptors
這新的Object.getOwnPropertyDescriptors
返回對象obj所有自身屬性描述。愛掏網 - it200.com這是一個多參數版本的Object.getOwnPropertyDescriptors(obj,propName)將會返回obj中propName屬性的一個單獨描述。愛掏網 - it200.com在我們日常不可變編程(immutable programming)時代中,有了這個方法很方便(記住,Javascript中對象是引用傳遞)在ES5中,開發者要使用
Object.assign()
來拷貝對象, Object.assign()
分配屬性只有copy和定義新的屬性。愛掏網 - it200.com當我們使用更加復雜對象和類原型,這可能會出問題。愛掏網 - it200.comObject.getOwnPropertyDescriptors
允許創建真實的對象淺副本并創建子類,它通過給開發者描述符來做到這一點.在Object.create(prototype, object)
放入描述符后,返回一個真正的淺拷貝。愛掏網 - it200.com
Object.create(
Object.getPrototypeOf(obj),
Object.getOwnPropertyDescriptors(obj)
)
或者可以合并兩個對象target
和source
如下:
Object.defineProperties(
target,
Object.getOwnPropertyDescriptors(source)
)
以上是Object.getOwnPropertyDesciptors
用法。愛掏網 - it200.com但是什么是描述符(descriptor)呢?就是一個對象的描述。愛掏網 - it200.com
1.數據描述符(Data descriptor)
2.存取器描述符(Accessor descriptor)
存取描述符有必須屬性:get 或者set或者get和set兩個就是如你所想的getter和setter函數,然后存取描述符還有可選屬性
configurable
和enumerable
let azatsBooks = { books: ['React Quickly'], get latest () { let numberOfBooks = this.books.length if (numberOfBooks == 0) return undefined return this.books[numberOfBooks - 1] } }
這個例子數據描述符books
由Object.getOwnPropertyDescriptor(azatsBooks, 'books')
產生結果如下:
Object configurable: true enumerable: true value: Array[1] writable: true __proto__: Object
同樣的,Object.getOwnPropertyDescriptor(azatsBooks, 'latest')
將會展現latest的描述符,這個latest(get)存取器描述符展現如下:
Object configurable: truee numerable: true get: latest() set: undefined __proto__: Object
現在我們調用新方法獲取所有的描述符:
console.log(Object.getOwnPropertyDescriptors(azatsBooks))
它會給出這個對象兩個描述符books和latest:
Object books: Object configurable: true enumerable: true value: Array[1] writable: true __proto__: Object latest: Object configurable: true enumerable: true get: latest() set: undefined __proto__: Object __proto__: Object
函數參數列表和調用中的尾逗號(Trailing commas)
尾逗號在函數定義中只是一個純粹語法變化,在ES5中,將會非法語法,在函數參數后面應該是沒有逗號的:
var f = function(a, b, c, d) { // NO COMMA! // ... console.log(d) } f(1,2,3,'this')
在ES8中,這種尾逗號是沒有問題的:
var f = function(a, b, c, d, ) { // COMMA? OK! // ... console.log(d) } f(1,2,3,'this')
var arr = [1, // Length == 3 2, 3, ] // let obj = {a: 1, // Only 3 properties b: 2, c: 3, } //
尾逗號主要有用在使用多行參數風格(典型的是那些很長的參數名),開發者終于可以忘記逗號放在第一位這種奇怪的寫法。愛掏網 - it200.com自從逗號bugs主要原因就是使用他們。愛掏網 - it200.com而現在你可以到處使用逗號,甚至最后參數都可以。愛掏網 - it200.com
異步函數(Async Functions)
異步函數(或者async/await)特性操作是Promise最重要的功能。愛掏網 - it200.com這種想法是為了在寫異步代碼中簡化它,因為人類大腦最討厭這種平行非序號思維了。愛掏網 - it200.com它只是不會演變這種方式。愛掏網 - it200.com本來以為Promise的到來已經是擺脫node異步的福音了,在ES8,異步函數是那么給力。愛掏網 - it200.com開發者定義一個asyc
函數里面不包含或者包含await 基于Promise異步操作。愛掏網 - it200.com在這引擎之下一個異步函數返回一個Promise,無論無何你在任何地方不會看到這樣的一個詞Promise。愛掏網 - it200.com
例如,在ES6中我們可以使用Promise,Axios庫向GraphQL服務器發送一個請求:
axios.get(`/q?query=${query}`) .then(response => response.data) .then(data => { this.props.processfetchedData(data) // Defined somewhere else }) .catch(error => console.log(error))
任何一個Promise庫都能兼容新的異步函數,我們可以使用同步try/catch做錯誤處理
async fetchData(url) => { try { const response = await axios.get(`/q?query=${query}`) const data = response.data this.props.processfetchedData(data) } catch (error) { console.log(error) } }
異步函數返回一個Promise,所以我們像下面可以繼續執行流程:
async fetchData(query) => { try { const response = await axios.get(`/q?query=${query}`) const data = response.data return data } catch (error) { console.log(error) } } fetchData(query).then(data => { this.props.processfetchedData(data) })
有了 async/await,我們的代碼執行異步看起來像執行同步一樣。愛掏網 - it200.com可以從頭到尾讀起來非常簡單和易懂,因為出現結果順序和函數題中從頭到尾順序一樣啊!
最后讓我以一幅圖(此圖笑噴我)結束今天的博客,今天是端午放假前,我還在這么認真的拼命的寫博客,哈哈哈

?reference:
?https://node.university/blog/498412/es7-es8-post
?
作者:zhoujie 出處:http://www.cnblogs.com/zhoujie/ 本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,不然我擔心博客園找你算賬 如果您覺得本文對你有幫助,請豎起您的大拇指右下角點推薦,也可以關注我