了解有關 JAVAScript 箭頭函數的所有信息。我們將向您展示如何使用 ES6 箭頭語法,以及在代碼中使用箭頭函數時需要注意的一些常見錯誤。你會看到很多例子來說明它們是如何工作的。
JavaScript 箭頭函數隨著 ECMAScript 2015(也稱為 ES6)的發布而出現。由于其簡潔的語法和對this關鍵字的處理,箭頭函數很快成為開發人員最喜歡的功能。
箭頭函數語法:重寫常規函數
函數就像食譜一樣,您可以在其中存儲有用的指令來完成您需要在程序中發生的事情,例如執行操作或返回值。通過調用您的函數,您可以執行配方中包含的步驟。每次調用該函數時都可以這樣做,而無需一次又一次地重寫配方。
這是聲明函數然后在 JavaScript 重新調用它的標準方法:
// function declaration
function sayHiStranger() {
return 'Hi, stranger!'
}
// call the function
sayHiStranger()
您還可以編寫與函數表達式相同的函數,如下所示:
const sayHiStranger = function () {
return 'Hi, stranger!'
}
JavaScript 箭頭函數始終是表達式。以下是使用粗箭頭符號重寫上述函數的方法:
const sayHiStranger = () => 'Hi, stranger'
這樣做的好處包括:
- 只有一行代碼
- 沒有function關鍵字
- 沒有return關鍵字
- 并且沒有畫括號 {}
在 JavaScript 中,函數是“一等公民”。您可以將函數存儲在變量中,將它們作為參數傳遞給其他函數,并將它們作為值從其他函數返回。您可以使用 JavaScript 箭頭函數完成所有這些操作。
無括號語法
在上面的例子中,函數沒有參數。()在這種情況下,您必須在粗箭頭 ( =>) 符號之前添加一組空括號。當您有多個參數時也是如此:
const getNetflixSeries = (seriesName, releaseDate) => `The ${seriesName} series was released in ${releaseDate}`
// call the function
console.log(getNetflixSeries('Bridgerton', '2020') )
// output: The Bridgerton series was released in 2020
但是,只需一個參數,您就可以繼續省略括號(您不必這樣做,但可以):
const favoriteSeries = seriesName => seriesName === "Bridgerton" ? "Let's watch it" : "Let's go out"
// call the function
console.log(favoriteSeries("Bridgerton"))
// output: "Let's watch it"
不過要小心。例如,如果您決定使用默認參數,則必須將其包裝在括號內:
// with parentheses: correct
const bestNetflixSeries = (seriesName = "Bridgerton") => `${seriesName} is the best`
// outputs: "Bridgerton is the best"
console.log(bestNetflixSeries())
// no parentheses: error
const bestNetflixSeries = seriesName = "Bridgerton" => `${seriesName} is the best`
// Uncaught SyntaxError: invalid arrow-function arguments (parentheses around the arrow-function may help)
僅僅因為你可以,并不意味著你應該。Kyle Simpson(以You Don't Know JS成名)夾雜著一點輕松、善意的諷刺,將他對省略括號的想法寫進了這個流程圖。
隱式返回
當函數體中只有一個表達式時,就可以使用 ES6 箭頭的語法更加簡潔。您可以將所有內容保持在一行,刪除花括號,并取消return關鍵字。
您剛剛在上面的示例中看到了這些漂亮的單行代碼是如何工作的。這里還有一個例子,只是為了很好的衡量。該orderByLikes()函數執行它在罐頭上所說的:也就是說,它返回一個按最高點贊數排序的 Netflix 系列對象數組:
// using the JS sort() function to sort the titles in descending order
// according to the number of likes (more likes at the top, fewer at the bottom
const orderByLikes = netflixSeries.sort( (a, b) => b.likes - a.likes )
// call the function
// output:the titles and the n. of likes in descending order
console.log(orderByLikes)
這很酷,但要注意代碼的可讀性——尤其是在使用單行和無括號的時候 ES6 箭頭語法對一堆箭頭函數進行排序時,就像在這個例子中一樣:
const greeter = greeting => name => `${greeting}, ${name}!`
那里發生了什么事?嘗試使用常規函數語法:
function greeter(greeting) {
return function(name) {
return `${greeting}, ${name}!`
}
}
現在,您可以快速了解外部函數如何greeter具有參數greeting,并返回匿名函數。這個內部函數又調用了一個參數,并使用和name的值返回一個字符串。以下是調用函數的方法:greetingname
const myGreet = greeter('Good morning')
console.log( myGreet('Mary') )
// output:
"Good morning, Mary!"
注意這些隱式返回錯誤
當您的 JavaScript 箭頭函數包含多個語句時,您需要將所有語句括在花括號中并使用return關鍵字。
在下面的代碼中,該函數構建了一個對象,其中包含一些 Netflix 系列的標題和摘要(Netflix 評論來自Rotten Tomatoes網站):
const seriesList = netflixSeries.map( series => {
const container = {}
container.title = series.name
container.summary = series.summary
// explicit return
return container
} )
函數內部的箭頭函數.map()由一系列語句發展而來,在語句結束時它返回一個對象。這使得在函數體周圍使用花括號是不可避免的。
此外,當您使用花括號時,隱式返回不是一種選擇。您必須使用return關鍵字。
如果您的函數使用隱式返回返回對象字面量,則需要將對象包裝在圓括號內。不過這樣做會導致錯誤,因為 JavaScript 引擎錯誤地將對象字面量的花括號解析為函數的花括號。正如您在上面剛剛注意到的,當您在箭頭函數中使用花括號時,您不能省略 return 關鍵字。
前面代碼的較短版本演示了這種語法:
// Uncaught SyntaxError: unexpected token: ':'
const seriesList = netflixSeries.map(series => { title: series.name });
// Works fine
const seriesList = netflixSeries.map(series => ({ title: series.name }));
你不能命名箭頭函數
function在關鍵字和參數列表之間沒有名稱標識符的函數稱為匿名函數。以下是常規匿名函數表達式的樣子:
const anonymous = function() {
return 'You can't identify me!'
}
箭頭函數都是匿名函數:
const anonymousArrowFunc = () => 'You can't identify me!'
name從 ES6 開始,變量和方法可以使用匿名函數的屬性從其語法位置推斷出匿名函數的名稱。這使得在檢查其值或報告錯誤時可以識別該函數。
使用以下方法檢查anonymousArrowFunc:
console.log(anonymousArrowFunc.name)
// output: "anonymousArrowFunc"
請注意,此推斷name屬性僅在將匿名函數分配給變量時才存在,如上面的示例中所示。如果您使用匿名函數作為回調,您將失去這個有用的功能。這在下面的演示中得到了例證,其中方法內的匿名函數.setInterval()無法利用該name屬性:
let counter = 5
let countDown = setInterval(() => {
console.log(counter)
counter--
if (counter === 0) {
console.log("I have no name!!")
clearInterval(countDown)
}
}, 1000)
這還不是全部。這個推斷name的屬性仍然不能作為一個正確的標識符,你可以使用它來從內部引用函數——例如遞歸、解除綁定事件等。
箭頭函數的內在匿名性導致 Kyle Simpson 表達了他對它們的看法如下:
由于我認為匿名函數不是在您的程序中經常使用的好主意,因此我不喜歡使用=>箭頭函數形式。——你不懂 JS
箭頭函數如何處理this關鍵字
關于箭頭函數要記住的最重要的事情是它們處理this關鍵字的方式。特別是,this箭頭函數內的關鍵字不會反彈。
為了說明這意味著什么,請查看下面的演示:
[codepen_embed height=”300″ default_tab=”html,result” slug_hash=”qBqgBmR” user=”SitePoint”]在 CodePen 上的SitePoint ( @SitePoint )
箭頭函數中查看 Pen JS。[/codepen_embed]
這是一個按鈕。單擊按鈕會觸發從 5 到 1 反向計數器,該計數器顯示在按鈕本身上。
<button class="start-btn">Start Counter</button>
...
const startBtn = document.querySelector(".start-btn");
startBtn.addEventListener('click', function() {
this.classList.add('counting')
let counter = 5;
const timer = setInterval(() => {
this.textContent = counter
counter --
if(counter < 0) {
this.textContent = 'THE END!'
this.classList.remove('counting')
clearInterval(timer)
}
}, 1000)
})
注意方法中的事件處理程序.addEventListener()是一個普通的匿名函數表達式,而不是箭頭函數。為什么?如果您this在函數內部登錄,您會看到它引用了已附加偵聽器的按鈕元素,這正是程序按計劃工作所期望的和需要的:
startBtn.addEventListener('click', function() {
console.log(this)
...
})
這是 Firefox 開發者工具控制臺中的樣子:
但是,嘗試用箭頭函數替換常規函數,如下所示:
startBtn.addEventListener('click', () => {
console.log(this)
...
})
現在,this不再引用該按鈕。相反,它引用了Window對象:
這意味著,如果您想在this單擊按鈕后向按鈕添加一個類,例如,您的代碼將不起作用:
// change button's border's Appearance
this.classList.add('counting')
這是控制臺中的錯誤消息:
在 JavaScript 中使用箭頭函數時,this關鍵字的值不會反彈。它繼承自父作用域(這稱為詞法作用域)。在這種特殊情況下,所討論的箭頭函數作為參數傳遞給startBtn.addEventListener()位于全局范圍內的方法。因此,this函數處理程序內部也綁定到全局范圍——即Window對象。
所以,如果要this在程序中引用開始按鈕,正確的做法是使用常規函數,而不是箭頭函數。
匿名箭頭函數
在上面的演示中,接下來要注意的是.setInterval()方法中的代碼。在這里,您也會找到一個匿名函數,但這次是箭頭函數。為什么?
請注意,如果您使用常規函數,值this會是什么:
const timer = setInterval(function() {
console.log(this)
...
}, 1000)
會是button元素嗎?一點也不。這將是Window對象!
事實上,上下文已經改變,因為this現在在一個未綁定或全局函數中,該函數作為參數傳遞給.setInterval(). 因此,this關鍵字的值也發生了變化,因為它現在綁定到全局范圍。
在這種情況下,一個常見的技巧是包含另一個變量來存儲this關鍵字的值,以便它繼續引用預期的元素——在這種情況下,button元素:
const that = this
const timer = setInterval(function() {
console.log(that)
...
}, 1000)
您還可以使用.bind()來解決問題:
const timer = setInterval(function() {
console.log(this)
...
}.bind(this), 1000)
使用箭頭函數,問題就完全消失了。這this是使用箭頭函數時的值:
const timer = setInterval( () => {
console.log(this)
...
}, 1000)
這一次,控制臺記錄了我們想要的按鈕。其實程序是要改變按鈕文字的,所以需要this引用button元素:
const timer = setInterval( () => {
console.log(this)
// the button's text displays the timer value
this.textContent = counter
}, 1000)
箭頭函數沒有自己的this上下文。他們繼承了this父級的價值,正是因為這個特性,他們在上述情況下做出了很好的選擇。
JavaScript 箭頭函數并不總是適合這項工作的工具
箭頭函數不僅僅是一種在 JavaScript 中編寫函數的新奇方式。它們有自己的局限性,這意味著在某些情況下您不想使用它們。上一個演示中的點擊處理程序就是一個很好的例子,但它不是唯一的。讓我們再檢查幾個。
箭頭函數作為對象方法
箭頭函數不能很好地作為對象上的方法。這是一個例子。
考慮這個netflixSeries對象,它有一些屬性和幾個方法。調用console.log(netflixSeries.getLikes())應該打印一條帶有當前點贊數的消息,調用console.log(netflixSeries.addLike())應該將點贊數加一,然后在控制臺上打印新值和感謝消息:
const netflixSeries = {
title: 'After Life',
firstRealease: 2019,
likes: 5,
getLikes: () => `${this.title} has ${this.likes} likes`,
addLike: () => {
this.likes++
return `Thank you for liking ${this.title}, which now has ${this.likes} likes`
}
}
相反,調用該.getLikes()方法返回“undefined has NaN likes”,調用該.addLike()方法返回“Thank you for like like undefined, which now has NaN likes”。所以,this.title并this.likes不能分別引用對象的屬性title和likes。
再一次,問題在于箭頭函數的詞法范圍。對象的this內部方法是引用父級的作用域,在這種情況下是Window對象,而不是父級本身——也就是說,不是netflixSeries對象。
當然,解決方案是使用常規函數:
const netflixSeries = {
title: 'After Life',
firstRealease: 2019,
likes: 5,
getLikes() {
return `${this.title} has ${this.likes} likes`
},
addLike() {
this.likes++
return `Thank you for liking ${this.title}, which now has ${this.likes} likes`
}
}
// call the methods
console.log(netflixSeries.getLikes())
console.log(netflixSeries.addLike())
// output:
After Life has 5 likes
Thank you for liking After Life, which now has 6 likes
第三方庫的箭頭函數
另一個需要注意的問題是第三方庫通常會綁定方法調用,以便this值指向有用的東西。
例如,在 jQuery 事件處理程序中,this您可以訪問處理程序綁定到的 DOM 元素:
$('body').on('click', function() {
console.log(this)
})
// <body>
但是如果我們使用箭頭函數——正如我們所見,它沒有自己的this上下文——我們會得到意想不到的結果:
$('body').on('click', () =>{
console.log(this)
})
// Window
這是使用Vue的另一個示例:
new Vue({
el: app,
data: {
message: 'Hello, World!'
},
created: function() {
console.log(this.message);
}
})
// Hello, World!
在created鉤子內部,this綁定到 Vue 實例,所以“Hello, World!” 顯示信息。
但是,如果我們使用箭頭函數,this它將指向沒有message屬性的父作用域:
new Vue({
el: app,
data: {
message: 'Hello, World!'
},
created: function() {
console.log(this.message);
}
})
// undefined
箭頭函數沒有arguments對象
有時,您可能需要創建一個參數數量不定的函數。例如,假設您要創建一個函數,按偏好排序列出您最喜歡的 Netflix 連續劇。但是,您還不知道要包含多少個系列。JavaScript 使arguments對象可用。這是一個類似數組的對象(不是完整的數組),它存儲調用時傳遞給函數的值。
嘗試使用箭頭函數實現此功能:
const listYourFavNetflixSeries = () => {
// we need to turn the arguments into a real array
// so we can use .map()
const favSeries = Array.from(arguments)
return favSeries.map( (series, i) => {
return `${series} is my #${i +1} favorite Netflix series`
} )
console.log(arguments)
}
console.log(listYourFavNetflixSeries('Bridgerton', 'Ozark', 'After Life'))
當您調用該函數時,您將收到以下錯誤消息:Uncaught ReferenceError: arguments is not defined. 這意味著該arguments對象在箭頭函數中不可用。事實上,用常規函數替換箭頭函數就可以了:
const listYourFavNetflixSeries = function() {
const favSeries = Array.from(arguments)
return favSeries.map( (series, i) => {
return `${series} is my #${i +1} favorite Netflix series`
} )
console.log(arguments)
}
console.log(listYourFavNetflixSeries('Bridgerton', 'Ozark', 'After Life'))
// output:
["Bridgerton is my #1 favorite Netflix series", "Ozark is my #2 favorite Netflix series", "After Life is my #3 favorite Netflix series"]
因此,如果您需要該arguments對象,則不能使用箭頭功能。
但是,如果您真的想使用箭頭函數來復制相同的功能怎么辦?您可以做的一件事是使用ES6 剩余參數( ...)。以下是重寫函數的方法:
const listYourFavNetflixSeries = (...seriesList) => {
return seriesList.map( (series, i) => {
return `${series} is my #${i +1} favorite Netflix series`
} )
}
結論
通過使用箭頭函數,您可以編寫帶有隱式返回的簡潔單行語句,并且最終忘記舊時的技巧來解決thisJavaScript 中關鍵字的綁定問題。箭頭函數也適用于數組方法,如.map(), .sort(), .forEach(),.filter()和.reduce()。但請記住:箭頭函數不會取代常規的 JavaScript 函數。請記住,僅當它們是適合工作的工具時才使用 JavaScript 箭頭函數。
如果本文對你有幫助,別忘記給我個3連 ,點贊,轉發,評論,,咱們下期見。
收藏 等于白嫖,點贊才是真情。
親愛的小伙伴們,有需要JAVA面試文檔資料請點贊+轉發,關注我后,私信我333就可以領取免費資料哦






