溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

JS箭頭函數(shù)的語法是什么及怎么使用

發(fā)布時(shí)間:2022-11-10 16:13:42 來源:億速云 閱讀:138 作者:iii 欄目:web開發(fā)

本篇內(nèi)容介紹了“JS箭頭函數(shù)的語法是什么及怎么使用”的有關(guān)知識(shí),在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

JavaScript的箭頭函數(shù)隨著ECMAScript 2015的發(fā)布而到來,也被稱為ES6。由于其簡潔的語法和對(duì)this關(guān)鍵字的處理,箭頭函數(shù)迅速成為開發(fā)者們最喜愛的功能。

箭頭函數(shù)語法

函數(shù)就像食譜一樣,你在其中存儲(chǔ)有用的指令,以完成你需要在程序中發(fā)生的事情,比如執(zhí)行一個(gè)動(dòng)作或返回一個(gè)值。通過調(diào)用函數(shù),來執(zhí)行食譜中包含的步驟。你可以在每次調(diào)用該函數(shù)時(shí)都這樣做,而不需要一次又一次地重寫菜譜。

下面是在JavaScript中聲明函數(shù)并調(diào)用它的標(biāo)準(zhǔn)方法:

// function declaration
function sayHiStranger() {
  return 'Hi, stranger!'
}

// call the function
sayHiStranger()

你也可以編寫同樣的函數(shù)作為函數(shù)表達(dá)式,就行這樣:

const sayHiStranger = function () {
  return 'Hi, stranger!'
}

JavaScript箭頭函數(shù)始終是表達(dá)式。下面是如何使用箭頭符號(hào)重寫上面的函數(shù):

const sayHiStranger = () => 'Hi, stranger'

這樣做的好處包括:

  • 代碼只有一行

  • 沒有function關(guān)鍵字

  • 沒有return關(guān)鍵字

  • 沒有大括號(hào){}

在JavaScript中,函數(shù)是一等公民。你可以把函數(shù)存儲(chǔ)在變量中,把它們作為參數(shù)傳遞給其他函數(shù),并從其他函數(shù)中把它們作為值返回。你可以使用JavaScript箭頭函數(shù)來做所有這些事情。

無圓括號(hào)語法

在上述示例中,函數(shù)是沒有參數(shù)的。在本例中,你必須在胖箭頭符號(hào)(=>)之前添加一對(duì)空的圓括號(hào)()。當(dāng)有多個(gè)參數(shù)時(shí)同理:

const getNetflixSeries = (seriesName, releaseDate) => `The ${seriesName} series was released in ${releaseDate}`// call the functionconsole.log(getNetflixSeries('Bridgerton', '2020') )// output: The Bridgerton series was released in 2020復(fù)制代碼

如果只有一個(gè)參數(shù),你可以省略圓括號(hào)(你不必如此,但你可以這么做):

const favoriteSeries = seriesName => seriesName === "Bridgerton" ? "Let's watch it" : "Let's go out"// call the functionconsole.log(favoriteSeries("Bridgerton"))// output: "Let's watch it"復(fù)制代碼

當(dāng)你這么做的時(shí)候要小心一點(diǎn)。比如說,你決定使用默認(rèn)參數(shù),你必須將其包裹在圓括號(hào)中:

// with parentheses: correctconst bestNetflixSeries = (seriesName = "Bridgerton") => `${seriesName} is the best`// outputs: "Bridgerton is the best"console.log(bestNetflixSeries())// no parentheses: errorconst bestNetflixSeries = seriesName = "Bridgerton" => `${seriesName} is the best`// Uncaught SyntaxError: invalid arrow-function arguments (parentheses around the arrow-function may help)復(fù)制代碼

隱式返回

在函數(shù)體內(nèi)只有一個(gè)表達(dá)式時(shí),你可以讓ES6的箭頭語法更加簡潔。你可以把所有內(nèi)容放在一行,去掉大括號(hào),并移除return關(guān)鍵字。

你已經(jīng)在上面的示例中看到了這些漂亮的一行代碼是如何工作的。下面的orderByLikes()函數(shù)返回奈飛劇集對(duì)象的數(shù)組,按照最高點(diǎn)贊數(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 bottomconst orderByLikes = netflixSeries.sort((a, b) => b.likes - a.likes)// call the function // output:the titles and the n. of likes in descending orderconsole.log(orderByLikes)復(fù)制代碼

這種寫法很酷,但是要注意代碼的可讀性。特別是在使用單行和無括號(hào)的ES6箭頭語法對(duì)一堆箭頭函數(shù)進(jìn)行排序時(shí)。就像這個(gè)例子:

const greeter = greeting => name => `${greeting}, ${name}!`

那里發(fā)生了什么?嘗試使用常規(guī)的函數(shù)語法:

function greeter(greeting) {  return function(name) {    return `${greeting}, ${name}!` 
  }
}

現(xiàn)在,你可以快速看到外部函數(shù)greeter如何具有參數(shù)greeting,并返回一個(gè)匿名函數(shù)。這個(gè)內(nèi)部函數(shù)又有一個(gè)叫做name的參數(shù),并使用greetingname的值返回一個(gè)字符串。下面是調(diào)用函數(shù)的方式:

const myGreet = greeter('Good morning')console.log( myGreet('Mary') )   

// output: "Good morning, Mary!"

注意隱式返回錯(cuò)誤

當(dāng)你的JavaScript箭頭函數(shù)包含不止一個(gè)語句,你需要在大括號(hào)內(nèi)包裹所有語句,并使用return關(guān)鍵字。

在下面的代碼中,該函數(shù)建立了一個(gè)包含幾個(gè)Netflix劇集的標(biāo)題和摘要的對(duì)象:

const seriesList = netflixSeries.map( series => {  const container = {}
  container.title = series.name 
  container.summary = series.summary

  // explicit return
  return container
} )

.map()函數(shù)中的箭頭函數(shù)在一系列的語句中展開,在語句的最后返回一個(gè)對(duì)象。這使得在函數(shù)主體周圍使用大括號(hào)是不可避免的。

另外,由于正在使用花括號(hào),隱式返回便不是一個(gè)選項(xiàng)。你必須顯式使用return關(guān)鍵字。

如果你的函數(shù)使用隱式返回來返回一個(gè)對(duì)象字面量,你需要使用圓括號(hào)來包裹該對(duì)象字面量。不這樣做將導(dǎo)致錯(cuò)誤,因?yàn)镴avaScript引擎將對(duì)象字面量的大括號(hào)錯(cuò)誤地解析為函數(shù)的大括號(hào)。正如你剛才注意到的,當(dāng)你在一個(gè)箭頭函數(shù)中使用大括號(hào)時(shí),你不能省略return關(guān)鍵字。

前面代碼的較短版本演示了這種語法:

// Uncaught SyntaxError: unexpected token: ':'const seriesList = netflixSeries.map(series => { title: series.name });// Works fineconst seriesList = netflixSeries.map(series => ({ title: series.name }));復(fù)制代碼

無法命名箭頭函數(shù)

function關(guān)鍵字和參數(shù)列表之間沒有名稱標(biāo)識(shí)的函數(shù)被稱為匿名函數(shù)。下面是常規(guī)匿名函數(shù)表達(dá)式的樣子:

const anonymous = function() {  return 'You can\'t identify me!' }

箭頭函數(shù)都是匿名函數(shù):

const anonymousArrowFunc = () => 'You can\'t identify me!'

從ES6開始,變量和方法可以通過匿名函數(shù)的語法位置,使用name屬性來推斷其名稱。這使得在檢查函數(shù)值或報(bào)告錯(cuò)誤時(shí)有可能識(shí)別該函數(shù)。

使用anonymousArrowFunc檢查一下:

console.log(anonymousArrowFunc.name)// output: "anonymousArrowFunc"

需要注意的是,只有當(dāng)匿名函數(shù)被分配給一個(gè)變量時(shí),這個(gè)可以推斷的name屬性才會(huì)存在,正如上面的例子。如果你使用匿名函數(shù)作為回調(diào)函數(shù),你就會(huì)失去這個(gè)有用的功能。在下面的演示中,.setInterval()方法中的匿名函數(shù)無法利用name屬性:

let counter = 5let countDown = setInterval(() => {  console.log(counter)
  counter--  if (counter === 0) {    console.log("I have no name!!")    clearInterval(countDown)
  }
}, 1000)

這還不是全部。這個(gè)推斷的name屬性仍然不能作為一個(gè)適當(dāng)?shù)臉?biāo)識(shí)符,你可以用它來指代函數(shù)本身--比如遞歸、解除綁定事件等。

如何處理this關(guān)鍵字

關(guān)于箭頭函數(shù),最重要的一點(diǎn)是它們處理this關(guān)鍵字的方式。特別是,箭頭函數(shù)內(nèi)的this關(guān)鍵字不會(huì)重新綁定。

為了說明這意味著什么,請(qǐng)查看下面的演示。

這里有一個(gè)按鈕。點(diǎn)擊按鈕會(huì)觸發(fā)一個(gè)從5到1的反向計(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()方法里面的事件處理器是一個(gè)常規(guī)的匿名函數(shù)表達(dá)式,而不是一個(gè)箭頭函數(shù)。為什么呢?如果在函數(shù)內(nèi)部打印this的值,你會(huì)看到它引用了監(jiān)聽器所連接的按鈕元素,這正是我們所期望的,也是程序按計(jì)劃工作所需要的:

startBtn.addEventListener('click', function() {  console.log(this)
  ...
})

下面是它在Firefox開發(fā)人員工具控制臺(tái)中的樣子:

JS箭頭函數(shù)的語法是什么及怎么使用

然后,嘗試使用箭頭函數(shù)來替代常規(guī)函數(shù),就像這樣:

startBtn.addEventListener('click', () => {  console.log(this)
  ...
})

現(xiàn)在,this不再引用按鈕元素。相反,它引用Window對(duì)象:

JS箭頭函數(shù)的語法是什么及怎么使用

這意味著,如果你想要在按鈕被點(diǎn)擊之后,使用this來為按鈕添加class,你的代碼就無法正常工作:

// change button's border's appearancethis.classList.add('counting')

下面是控制臺(tái)中的錯(cuò)誤信息:

JS箭頭函數(shù)的語法是什么及怎么使用

當(dāng)你在JavaScript中使用箭頭函數(shù),this關(guān)鍵字的值不會(huì)被重新綁定。它繼承自父作用域(也稱為詞法作用域)。在這種特殊情況下,箭頭函數(shù)被作為參數(shù)傳遞給startBtn.addEventListener()方法,該方法位于全局作用域中。因此,函數(shù)處理器中的this也被綁定到全局作用域中--也就是Window對(duì)象。

因此,如果你想讓this引用程序中的開始按鈕,正確的做法是使用一個(gè)常規(guī)函數(shù),而不是一個(gè)箭頭函數(shù)。

匿名箭頭函數(shù)

在上面的演示中,接下來要注意的是.setInterval()方法中的代碼。在這里,你也會(huì)發(fā)現(xiàn)一個(gè)匿名函數(shù),但這次是一個(gè)箭頭函數(shù)。為什么?

請(qǐng)注意,如果你使用常規(guī)函數(shù),this值會(huì)是多少:

const timer = setInterval(function() {  console.log(this)
  ...
}, 1000)

button元素嗎?并不是。這個(gè)值將會(huì)是Window對(duì)象!

事實(shí)上,上下文已經(jīng)發(fā)生了變化,因?yàn)楝F(xiàn)在this在一個(gè)非綁定的或全局的函數(shù)中,它被作為參數(shù)傳遞給.setInterval() 。因此,this關(guān)鍵字的值也發(fā)生了變化,因?yàn)樗F(xiàn)在被綁定到全局作用域。

在這種情況下,一個(gè)常見的hack手段是包括另一個(gè)變量來存儲(chǔ)this關(guān)鍵字的值,這樣它就會(huì)一直指向預(yù)期的元素--在這種情況下,就是button元素:

const that = thisconst timer = setInterval(function() {  console.log(that)
  ...
}, 1000)

你也可以使用.bind()來解決這個(gè)問題:

const timer = setInterval(function() {  console.log(this)
  ...
}.bind(this), 1000)

有了箭頭函數(shù),問題就徹底消失了。下面是使用箭頭函數(shù)時(shí)this的值:

const timer = setInterval( () => { 
  console.log(this)
  ...
}, 1000)

JS箭頭函數(shù)的語法是什么及怎么使用

這次,控制臺(tái)打印了button,這就是我們想要的。事實(shí)上,程序要改變按鈕的文本,所以它需要this來指代button元素:

const timer = setInterval( () => { 
  console.log(this) // the button's text displays the timer value
  this.textContent = counter
}, 1000)

箭頭函數(shù)沒有自己的this上下文。它們從父級(jí)繼承this的值,正是因?yàn)檫@個(gè)特點(diǎn),在上面這種情況下就是很好的選擇。

不正常工作的情況

箭頭函數(shù)并不只是在JavaScript中編寫函數(shù)的一種花里胡哨的新方法。它們有自己的局限性,這意味著在有些情況下你不想使用箭頭函數(shù)。讓我們看看更多的例子。

箭頭函數(shù)作為對(duì)象方法

箭頭函數(shù)作為對(duì)象上的方法不能很好地工作。

考慮這個(gè)netflixSeries對(duì)象,上面有一些屬性和一系列方法。調(diào)用console.log(netflixSeries.getLikes()) 應(yīng)該會(huì)打印一條信息,說明當(dāng)前喜歡的人數(shù)。console.log(netflixSeries.addLike())應(yīng)該會(huì)增加一個(gè)喜歡的人數(shù),然后在控制臺(tái)上打印新值:

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 liking undefined, which now has NaN likes'。因此,this.titlethis.likes未能分別引用對(duì)象的屬性titlelikes。

這次,問題出在箭頭函數(shù)的詞法作用域上。對(duì)象方法中的this引用的是父對(duì)象的范圍,在本例中是Window對(duì)象,而不是父對(duì)象本身--也就是說,不是netflixSeries對(duì)象。

當(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 likesThank you for liking After Life, which now has 6 likes復(fù)制代碼

箭頭函數(shù)與第三方庫

另一個(gè)需要注意的問題是,第三方庫通常會(huì)綁定方法調(diào)用,因此this值會(huì)指向一些有用的東西。

比如說,在Jquery事件處理器內(nèi)部,this將使你能夠訪問處理器所綁定的DOM元素:

$('body').on('click', function() {  console.log(this)
})// <body>

但是如果我們使用箭頭函數(shù),正如我們所看到的,它沒有自己的this上下文,我們會(huì)得到意想不到的結(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í)例上,因此會(huì)顯示'Hello, World!'信息。

然而如果我們使用箭頭函數(shù),this將會(huì)指向父作用域,上面沒有message屬性:

new Vue({  el: app,  data: {    message: 'Hello, World!'
  },  created: () => {    console.log(this.message);
  }
})// undefined

箭頭函數(shù)沒有arguments對(duì)象

有時(shí),你可能需要?jiǎng)?chuàng)建一個(gè)具有無限參數(shù)個(gè)數(shù)的函數(shù)。比如,假設(shè)你想創(chuàng)建一個(gè)函數(shù),列出你最喜歡的奈飛劇集,并按照偏好排序。然而,你還不知道你要包括多少個(gè)劇集。JavaScript提供了arguments對(duì)象。這是一個(gè)類數(shù)組對(duì)象(不是完整的數(shù)組),在調(diào)用時(shí)存儲(chǔ)傳遞給函數(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ù)時(shí),你會(huì)得到以下錯(cuò)誤:Uncaught ReferenceError: arguments is not defined。這意味著arguments對(duì)象在箭頭函數(shù)中是不可用的。事實(shí)上,將箭頭函數(shù)替換成常規(guī)函數(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"]復(fù)制代碼

因此,如果你需要arguments對(duì)象,你不能使用箭頭函數(shù)。

但如果你真的想用一個(gè)箭頭函數(shù)來復(fù)制同樣的功能呢?你可以使用ES6剩余參數(shù)(...)。下面是你該如何重寫你的函數(shù):

const listYourFavNetflixSeries = (...seriesList) => {   return seriesList.map( (series, i) => {     return `${series} is my #${i +1} favorite Netflix series`
   } )
 }

“JS箭頭函數(shù)的語法是什么及怎么使用”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

js
AI