JavaScriptES6中的前五項功能值得掌握
JavaScriptES6為JavaScript語言添加了一系列新特性,其中一些特性更具有開拓性,而且比其他特性更適用。像ES6類例如,雖然新穎,但在現有的JavaScript類建立方法的基礎上添加了語法糖,而生成器等功能雖然非常強大,但卻保留給更專門的任務。
從過去12個月從事各種JavaScript相關專案來看,我發現ES6的五個最重要的特性是必不可少的,因為它們真正簡化了JavaScript中常見任務的完成方式。你的前五名可能與我的不同,如果他們是,我鼓勵你分享在評論部分的結尾。
開始吧!
-
箭頭函式
-
承諾
-
非同步函式
-
解構
-
預設和REST引數
1)JavaScript Arrow函式
在ES6JavaScript中,我最喜歡的一個新增功能不是一個新特性,而是一個令人耳目一新的新語法集,每當我使用它時,它都會讓我面帶微笑。我說的是Arrow函式,它提供了一種非常優雅和極簡的方法來定義JavaScript中的匿名函式。
簡而言之,Arrow函式會刪除“function
“關鍵字,並使用箭頭(=>
)將函式的函式體中的引數部分。匿名職能:
1 |
(x, y) => x * y;
|
這相當於:
1 2 3 |
function (x, y){
return x * y;
}
|
或:
1 2 3 4 |
(x, y) => {
var factor = 5;
var growth = (x-y) * factor;
}
|
與以下內容相同:
1 2 3 4 |
function (x, y){
var factor = 5;
var growth = (x-y) * factor;
}
|
使用傳統的匿名函式時,箭頭函式還移除一個關鍵錯誤源,即this
“函式中的物件。使用Arrow函式,“this
“在詞彙上是繫結的,這是隻是一種奇特的表達方式,它的值被繫結到父範圍,並且永不改變。如果 箭函式在自定義物件中定義為“countup
的價值this
“指向”countup
“-沒有任何猜測。例如:
1 2 3 4 5 6 7 8 9 10 11 |
var countup = {
counter: 15,
start: function (){
window.addEventListener( 'click' , () => {
alert( this .counter) // correctly alerts 15 due to lexical binding of this
})
}
};
countup.start();
|
將其與傳統的匿名函式進行比較,其中“this
“更改取決於在其中定義的上下文。試圖引用的結果this.counter
在上述情況下將返回undefined
這種行為可能會使許多人不熟悉動態繫結的複雜性。對於Arrow函式,“this
“總是可以預測和容易推斷的。
有關“箭上的瘦身”功能,請參閱“JavaScriptArrow函式概述".
2)JavaScript承諾
JavaScriptES6承諾簡化非同步任務的處理方式,這是一個在大多數現代Web應用程式中發揮作用的任務。JavaScript承諾使用一種中心的、直觀的機制來跟蹤和響應非同步事件,而不是依賴回撥函式(由jQuery等JavaScript框架推廣)。它不僅使除錯非同步程式碼變得更加容易,而且編寫非同步程式碼也是一種樂趣。
所有JavaScript承諾的生存和死亡Promise()
構造者:
1 2 3 4 5 |
const mypromise = new Promise( function (resolve, reject){
// asynchronous code to run here
// call resolve() to indicate task successfully completed
// call reject() to indicate task has failed
})
|
使用resolve()
和reject()
方法在內部,當承諾被履行和拒絕時,我們可以分別向承諾物件發出訊號。這,這個,那,那個then()
和catch()
然後可以呼叫方法來處理完全填充或被拒絕的承諾的後果。
我一直使用以下承諾的變體注入XMLHttpRequest函式,依次檢索外部檔案的內容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
function getasync(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.open( "GET" , url)
xhr.onload = () => resolve(xhr.responseText)
xhr.onerror = () => reject(xhr.statusText)
xhr.send()
})
}
getasync( 'test.txt' ).then((msg) => {
console.log(msg) // echos contents of text.txt
return getasync( 'test2.txt' )
}).then((msg) => {
console.log(msg) // echos contents of text2.txt
return getasync( 'test3.txt' )
}).then((msg) => {
console.log(msg) // echos contents of text3.txt
})
|
要掌握JavaScript承諾的關鍵方面,例如連結承諾和並行執行承諾,請閱讀“承諾初學者指南".
3)JavaScript非同步函式
除了JavaScript承諾之外,非同步函式還進一步重寫了傳統非同步程式碼的構造,使其更加可讀性更強,更易於理解。每當我向客戶顯示程式碼時async
函式交織在一起,第一反應總是令人驚訝,接著是強烈的好奇心,以瞭解它是如何工作的。
非同步函式由兩部分組成:
1)以字首為字首的正則函式async
功能
1 2 3 4 |
async function fetchdata(url){
// Do something
// Always returns a promise
}
|
2)使用await
關鍵字在主非同步函式中非同步函式呼叫之前。
一個例子勝過千言萬語。下面是上面基於承諾的示例的重寫,以供使用非同步函式相反:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
function getasync(url) { // same as original function
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.open( "GET" , url)
xhr.onload = () => resolve(xhr.responseText)
xhr.onerror = () => reject(xhr.statusText)
xhr.send()
})
}
async function fetchdata(){ // main Async function
var text1 = await getasync( 'test.txt' )
console.log(text1)
var text2 = await getasync( 'test2.txt' )
console.log(text2)
var text3 = await getasync( 'test3.txt' )
console.log(text3)
return "Finished"
}
fetchdata().then((msg) =>{
console.log(msg) // logs "finished"
})
|
上面的示例在執行時按順序回顯“test.txt”、“test2.txt”、“test3.txt”以及最後“Finish”的內容。
如您所見,在非同步函式,我們呼叫非同步函式。getasync()
好像是同步的-不then()
方法或回撥函式,以向下一步發出訊號。無論何時await
關鍵字時,執行將暫停,直到 getasync()
在移到非同步函式中的下一行之前已解析。結果與基於純承諾的方法相同,使用了一系列的then()
方法。
掌握非同步函式,包括如何執行await
函式並行,讀為“JavaScript非同步函式簡介-承諾簡化".
4)JavaScript析構
除了Arrow函式之外,這是我每天使用最多的ES6功能。ES6解構不是一種新特性,而是一種新的賦值語法,它允許您快速地從物件屬性和陣列中解壓縮值,並將它們分配給各個變數。
1 2 3 4 |
var profile = {name: 'George' , age:39, hobby: 'Tennis' }
var {name, hobby} = profile // destructure profile object
console.log(name) // "George"
console.log(hobby) // "Tennis"
|
在這裡,我使用析構來快速提取name
和hobby
屬性的profile
物件。
使用別名,您可以使用不同的變數名,而不是從其中提取值的對應物件屬性:
1 2 3 4 |
var profile = {name: 'George' , age:39, hobby: 'Tennis' }
var {name:n, hobby:h} = profile // destructure profile object
console.log(n) // "George"
console.log(h) // "Tennis"
|
巢狀物件析構
析構也適用於巢狀物件,我一直使用這些物件來快速解壓縮複雜JSON請求中的值:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
var jsondata = {
title: 'Top 5 JavaScript ES6 Features' ,
Details: {
date: {
created: '2017/09/19' ,
modified: '2017/09/20' ,
},
Category: 'JavaScript' ,
},
url: '/top-5-es6-features/'
};
var {title, Details: {date: {created, modified}}} = jsondata
console.log(title) // 'Top 5 JavaScript ES6 Features'
console.log(created) // '2017/09/19'
console.log(modified) // '2017/09/20'
|
分解陣列
對陣列的解構作用類似於物件,除非在左邊使用方括號,而不是左邊的大括號:
1 2 3 4 |
var soccerteam = [ 'George' , 'Dennis' , 'Sandy' ]
var [a, b] = soccerteam // destructure soccerteam array
console.log(a) // "George"
console.log(b) // "Dennis"
|
在使用逗號(,)解壓其元素時,可以跳過某些陣列元素:
1 2 3 4 |
var soccerteam = [ 'George' , 'Dennis' , 'Sandy' ]
var [a,,b] = soccerteam // destructure soccerteam array
console.log(a) // "George"
console.log(b) // "Sandy"
|
對我來說,析構消除了提取和分配物件屬性的所有摩擦,並以傳統的方式對陣列進行了值處理。若要充分了解ES6破壞的複雜性和潛力,請閱讀“掌握ES6:破壞".
5)預設引數和REST引數
最後,我想提出的ES6接下來的兩個特性主要是處理函式引數。我們在JavaScript中建立的幾乎每個函式都接受使用者資料,因此這兩個特性肯定會在滿月時不止一次地派上用場。
預設引數
在使用應該具有預設值的引數建立函式時,我們都使用了以下模式:
1 2 3 4 5 |
function getarea(w,h){
var w = w || 10
var h = h || 15
return w * h
}
|
由於ES6對預設引數的支援,顯式定義引數值的測試結束了:
1 2 3 4 |
function getarea(w=10, h=15){
return w * h
}
getarea(5) // returns 75
|
更多關於ES6中預設引數的詳細資訊這裡.
休息引數
ES6中的REST引數很容易將函式引數轉換為陣列,以便於操作。
1 2 3 4 5 |
function addit(...theNumbers){
return theNumbers.reduce((prevnum, curnum) => prevnum + curnum, 0) // get the sum of the array elements
}
addit(1,2,3,4) // returns 10
|
通過在命名引數前面加上3個點(.),在該位置輸入到函式中的引數將自動轉換為陣列。
如果沒有REST引數,我們將不得不做一些像下面這樣複雜的事情手動將引數轉換為陣列第一:
1 2 3 4 5 6 |
function addit(theNumbers){
var numArray = Array.prototype.slice.call(arguments) // force arguments object into array
return numArray.reduce((prevnum, curnum) => prevnum + curnum, 0)
}
addit(1,2,3,4) // returns 10
|
REST引數僅可應用於函式引數的子集,如以下所示,它只將從第2段開始的引數轉換為陣列:
1 2 3 4 5 |
function f1(date, ...lucknumbers){
return 'The Lucky Numbers for ' + date + ' are: ' + lucknumbers.join( ', ' )
}
alert( f1( '2017/09/29' , 3, 32, 43, 52) ) // alerts "The Lucky Numbers for 2017/09/29 are 3,32,43,52"
|
關於ES6中REST引數的完整規範,看這裡.
結語
你同意我的前5項ES6功能嗎?你最常使用的是哪一種?請分享以下評論。