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