深入了解JavaScript箭頭函數。我們將向您展示如何使用ES6箭頭語法,以及在代碼中使用箭頭函數時需要注意的一些常見錯誤。您將看到許多說明其工作原理的示例。
ECMAScript 2015(也稱為ES6)發布後,JavaScript箭頭函數隨之出現。由於其簡潔的語法和對this
關鍵字的處理方式,箭頭函數迅速成為開發人員最喜歡的功能之一。
function
關鍵字、花括號{}
以及只有一個表達式時的return
關鍵字,在JavaScript中提供了簡潔的語法。 this
關鍵字捕獲其值來自定義箭頭函數的封閉上下文,而不是其被調用的位置,這使其適用於傳統函數表達式需要綁定到外部this
上下文的情況。 function
構造函數時,因為它們具有詞法this
綁定並且缺少arguments
對象。 .map()
、.sort()
、.forEach()
、.filter()
和.reduce()
)一起使用時,它們可以增強可讀性和簡潔性,但必須注意確保它們是在特定上下文中適合這項工作的正確工具。 函數就像食譜,您可以在其中存儲有用的指令來完成程序中需要發生的事情,例如執行操作或返回值。通過調用您的函數,您可以執行食譜中包含的步驟。每次調用該函數時,您都可以這樣做,而無需一遍遍地重寫食譜。
以下是聲明函數並在JavaScript中調用它的標準方法:
// 函数声明 function sayHiStranger() { return 'Hi, stranger!' } // 调用函数 sayHiStranger()
您也可以將相同的函數編寫為函數表達式,如下所示:
const sayHiStranger = function () { return 'Hi, stranger!' }
JavaScript箭頭函數始終是表達式。以下是如何使用胖箭頭表示法將上面的函數重寫為箭頭函數表達式:
const sayHiStranger = () => 'Hi, stranger'
其優點包括:
function
關鍵字return
關鍵字{}
在JavaScript中,函數是“一等公民”。您可以將函數存儲在變量中,將它們作為參數傳遞給其他函數,並將其作為值從其他函數返回。您可以使用JavaScript箭頭函數執行所有這些操作。
在上面的示例中,函數沒有參數。在這種情況下,您必須在胖箭頭(=>)符號之前添加一組空括號()。當您創建具有多個參數的函數時,情況也是如此:
// 函数声明 function sayHiStranger() { return 'Hi, stranger!' } // 调用函数 sayHiStranger()
但是,只有一個參數時,您可以省略括號(不必這樣做,但可以):
const sayHiStranger = function () { return 'Hi, stranger!' }
但是要小心。例如,如果您決定使用默認參數,則必須將其括在括號中:
const sayHiStranger = () => 'Hi, stranger'
僅僅因為您可以,並不意味著您應該這樣做。伴隨著一些輕鬆愉快的、善意的諷刺,Kyle Simpson(《你不知道JS》的作者)將他關於省略括號的想法放入了這個流程圖中。 (此處應插入流程圖,但由於無法直接插入圖片,此處省略)
當函數體中只有一個表達式時,您可以使ES6箭頭語法更加簡潔。您可以將所有內容都放在一行上,刪除花括號,並去掉return
關鍵字。
您剛才已經看到了這些簡潔的一行代碼是如何在上面的示例中工作的。再舉一個例子,僅供參考。 orderByLikes()函數的功能正如其名:它返回一個按點贊數最高的順序排列的Netflix系列對像數組:
const getNetflixSeries = (seriesName, releaseDate) => `The ${seriesName} series was released in ${releaseDate}` // 调用函数 console.log(getNetflixSeries('Bridgerton', '2020') ) // 输出:The Bridgerton series was released in 2020
這很酷,但是要注意代碼的可讀性——尤其是在使用一行代碼和無括號ES6箭頭語法對一堆箭頭函數進行排序時,例如在此示例中:
const favoriteSeries = seriesName => seriesName === "Bridgerton" ? "Let's watch it" : "Let's go out" // 调用函数 console.log(favoriteSeries("Bridgerton")) // 输出:"Let's watch it"
那裡發生了什麼?嘗試使用常規函數語法:
// 使用括号:正确 const bestNetflixSeries = (seriesName = "Bridgerton") => `${seriesName} is the best` // 输出:"Bridgerton is the best" console.log(bestNetflixSeries()) // 没有括号:错误 const bestNetflixSeries = seriesName = "Bridgerton" => `${seriesName} is the best` // Uncaught SyntaxError: invalid arrow-function arguments (parentheses around the arrow-function may help)
現在,您可以快速了解外部函數greeter如何具有一個參數greeting,並返回一個匿名函數。反過來,這個內部函數又有一個名為name的參數,並使用greeting和name的值返回一個字符串。以下是如何調用該函數:
// 使用JS sort()函数按点赞数降序排列标题(点赞数越多,排名越高,点赞数越少,排名越低) const orderByLikes = netflixSeries.sort( (a, b) => b.likes - a.likes ) // 调用函数 // 输出:按降序排列的标题和点赞数 console.log(orderByLikes)
當您的JavaScript箭頭函數包含多個語句時,您需要將所有語句都括在花括號中並使用return
關鍵字。
在下面的代碼中,該函數構建一個包含一些Netflix系列標題和摘要的對象(Netflix評論來自爛番茄網站):
const greeter = greeting => name => `${greeting}, ${name}!`
.map()
函數內的箭頭函數通過一系列語句展開,最後返回一個對象。這使得在函數體周圍使用花括號不可避免。
此外,由於您使用的是花括號,因此隱式返回不是一種選擇。您必須使用return
關鍵字。
如果您的函數使用隱式返回返回對象字面量,則需要將對象括在圓括號中。如果不這樣做,將導致錯誤,因為JavaScript引擎錯誤地將對象字面量的花括號解析為函數的花括號。正如您剛才在上面注意到的那樣,當您在箭頭函數中使用花括號時,您不能省略return
關鍵字。
前面代碼的較短版本演示了此語法:
// 函数声明 function sayHiStranger() { return 'Hi, stranger!' } // 调用函数 sayHiStranger()
在function
關鍵字和參數列表之間沒有名稱標識符的函數稱為匿名函數。以下是常規匿名函數表達式的外觀:
const sayHiStranger = function () { return 'Hi, stranger!' }
箭頭函數都是匿名函數:
const sayHiStranger = () => 'Hi, stranger'
從ES6開始,變量和方法可以根據其句法位置推斷匿名函數的名稱,使用其name
屬性。這使得在檢查其值或報告錯誤時可以識別該函數。
使用anonymousArrowFunc檢查一下:
const getNetflixSeries = (seriesName, releaseDate) => `The ${seriesName} series was released in ${releaseDate}` // 调用函数 console.log(getNetflixSeries('Bridgerton', '2020') ) // 输出:The Bridgerton series was released in 2020
請注意,此推斷的name
屬性僅在匿名函數分配給變量時才存在,如上面的示例所示。如果您將匿名函數用作回調函數,則會失去此實用功能。下面的演示說明了這一點,其中.setInterval()
方法中的匿名函數無法使用name
屬性:
const favoriteSeries = seriesName => seriesName === "Bridgerton" ? "Let's watch it" : "Let's go out" // 调用函数 console.log(favoriteSeries("Bridgerton")) // 输出:"Let's watch it"
而且不止如此。此推斷的name
屬性仍然不能用作您可以從函數內部引用該函數的適當標識符——例如用於遞歸、取消綁定事件等。
箭頭函數的內在匿名性導致Kyle Simpson表達了他對它們的看法如下:
由於我認為匿名函數不適合經常在程序中使用,所以我並不喜歡使用=>箭頭函數形式。 ——《你不知道JS》
關於箭頭函數,最重要的是要記住它們處理this
關鍵字的方式。特別是,箭頭函數內部的this
關鍵字不會重新綁定。
為了說明這意味著什麼,請查看下面的演示:(此處應插入代碼Pen,但由於無法直接插入代碼Pen,此處省略)
這是一個按鈕。單擊按鈕會觸發從5到1的反向計數器,該計數器顯示在按鈕本身上。
// 使用括号:正确 const bestNetflixSeries = (seriesName = "Bridgerton") => `${seriesName} is the best` // 输出:"Bridgerton is the best" console.log(bestNetflixSeries()) // 没有括号:错误 const bestNetflixSeries = seriesName = "Bridgerton" => `${seriesName} is the best` // Uncaught SyntaxError: invalid arrow-function arguments (parentheses around the arrow-function may help)
請注意.addEventListener()
方法中的事件處理程序是如何一個常規匿名函數表達式,而不是箭頭函數。為什麼?如果您在函數內部記錄this
,您將看到它引用了已附加偵聽器的按鈕元素,這正是預期的結果,也是程序按計劃工作所需的。
// 使用JS sort()函数按点赞数降序排列标题(点赞数越多,排名越高,点赞数越少,排名越低) const orderByLikes = netflixSeries.sort( (a, b) => b.likes - a.likes ) // 调用函数 // 输出:按降序排列的标题和点赞数 console.log(orderByLikes)
在Firefox開發者工具控制台中,它的外觀如下:(此處應插入圖片,但由於無法直接插入圖片,此處省略)
但是,嘗試將常規函數替換為箭頭函數,如下所示:
// 函数声明 function sayHiStranger() { return 'Hi, stranger!' } // 调用函数 sayHiStranger()
現在,this
不再引用按鈕了。相反,它引用了Window對象:(此處應插入圖片,但由於無法直接插入圖片,此處省略)
這意味著,如果您想在單擊按鈕後使用this
向按鈕添加一個類,您的代碼將無法工作,如下例所示:
const sayHiStranger = function () { return 'Hi, stranger!' }
控制台中的錯誤消息如下:(此處應插入圖片,但由於無法直接插入圖片,此處省略)
當您在JavaScript中使用箭頭函數時,this
關鍵字的值不會重新綁定。它繼承自父作用域(這稱為詞法作用域)。在此特定情況下,所討論的箭頭函數作為參數傳遞給startBtn.addEventListener()
方法,該方法位於全局作用域中。因此,函數處理程序中的this
也綁定到全局作用域——即Window對象。
因此,如果您希望this
引用程序中的啟動按鈕,正確的方法是使用常規函數,而不是箭頭函數。
接下來要注意的是上面的演示中.setInterval()
方法中的代碼。在這裡,您也會找到一個匿名函數,但這次是一個箭頭函數。為什麼?
請注意,如果您使用常規函數,this
的值將是什麼:
const sayHiStranger = () => 'Hi, stranger'
它會是按鈕元素嗎?根本不會。它將是Window對象! (此處應插入圖片,但由於無法直接插入圖片,此處省略)
事實上,上下文已經改變,因為this
現在在一個未綁定或全局函數中,該函數作為參數傳遞給.setInterval()
。因此,this
關鍵字的值也發生了變化,因為它現在綁定到全局作用域。
在這種情況下,一種常見的技巧是包含另一個變量來存儲this
關鍵字的值,以便它繼續引用預期的元素——在本例中為按鈕元素:
const getNetflixSeries = (seriesName, releaseDate) => `The ${seriesName} series was released in ${releaseDate}` // 调用函数 console.log(getNetflixSeries('Bridgerton', '2020') ) // 输出:The Bridgerton series was released in 2020
您也可以使用.bind()
來解決這個問題:
const favoriteSeries = seriesName => seriesName === "Bridgerton" ? "Let's watch it" : "Let's go out" // 调用函数 console.log(favoriteSeries("Bridgerton")) // 输出:"Let's watch it"
使用箭頭函數,問題完全消失了。以下是使用箭頭函數時this
的值:
// 使用括号:正确 const bestNetflixSeries = (seriesName = "Bridgerton") => `${seriesName} is the best` // 输出:"Bridgerton is the best" console.log(bestNetflixSeries()) // 没有括号:错误 const bestNetflixSeries = seriesName = "Bridgerton" => `${seriesName} is the best` // Uncaught SyntaxError: invalid arrow-function arguments (parentheses around the arrow-function may help)
(此處應插入圖片,但由於無法直接插入圖片,此處省略)
這次,控制台記錄了按鈕,這就是我們想要的。事實上,程序將更改按鈕文本,因此它需要this
來引用按鈕元素:
// 使用JS sort()函数按点赞数降序排列标题(点赞数越多,排名越高,点赞数越少,排名越低) const orderByLikes = netflixSeries.sort( (a, b) => b.likes - a.likes ) // 调用函数 // 输出:按降序排列的标题和点赞数 console.log(orderByLikes)
箭頭函數沒有自己的this
上下文。它們繼承自父級的this
值,正是由於此功能,它們才成為在上述情況下的絕佳選擇。
箭頭函數不僅僅是編寫JavaScript函數的一種花哨的新方法。它們有其自身的局限性,這意味著有些情況下您不希望使用它。前面的演示中的點擊處理程序就是一個例子,但這並不是唯一的一個。讓我們再檢查幾個。
箭頭函數不能很好地用作對象的方法。這是一個例子。
考慮這個netflixSeries對象,它有一些屬性和幾個方法。調用console.log(netflixSeries.getLikes())
應該打印一條包含當前點贊數的消息,調用console.log(netflixSeries.addLike())
應該將點贊數增加一,然後在控制台中打印新值和感謝消息:
// 函数声明 function sayHiStranger() { return 'Hi, stranger!' } // 调用函数 sayHiStranger()
相反,調用.getLikes()
方法返回“undefined has NaN likes”,調用.addLike()
方法返回“Thank you for liking undefined, which now has NaN likes”。因此,this.title
和this.likes
無法分別引用對象的屬性title
和likes
。
同樣,問題在於箭頭函數的詞法作用域。對象方法中的this
正在引用父作用域,在本例中是Window對象,而不是父對象本身——即不是netflixSeries對象。
當然,解決方案是使用常規函數:
const sayHiStranger = function () { return 'Hi, stranger!' }
另一個需要注意的是,第三方庫通常會綁定方法調用,以便this
值指向有用的內容。
例如,在jQuery事件處理程序中,this
將允許您訪問已綁定處理程序的DOM元素:
const sayHiStranger = () => 'Hi, stranger'
但是,如果我們使用箭頭函數——正如我們已經看到的,它沒有自己的this
上下文——我們會得到意想不到的結果:
const getNetflixSeries = (seriesName, releaseDate) => `The ${seriesName} series was released in ${releaseDate}` // 调用函数 console.log(getNetflixSeries('Bridgerton', '2020') ) // 输出:The Bridgerton series was released in 2020
這是一個使用Vue的進一步示例:
const favoriteSeries = seriesName => seriesName === "Bridgerton" ? "Let's watch it" : "Let's go out" // 调用函数 console.log(favoriteSeries("Bridgerton")) // 输出:"Let's watch it"
在created
鉤子中,this
綁定到Vue實例,因此顯示“Hello, World!”消息。
但是,如果我們使用箭頭函數,this
將指向父作用域,該作用域沒有message
屬性:
// 使用括号:正确 const bestNetflixSeries = (seriesName = "Bridgerton") => `${seriesName} is the best` // 输出:"Bridgerton is the best" console.log(bestNetflixSeries()) // 没有括号:错误 const bestNetflixSeries = seriesName = "Bridgerton" => `${seriesName} is the best` // Uncaught SyntaxError: invalid arrow-function arguments (parentheses around the arrow-function may help)
有時,您可能需要創建一個具有不確定數量參數的函數。例如,假設您想創建一個按偏好順序列出您最喜歡的Netflix系列的函數。但是,您還不知道您要包含多少個系列。 JavaScript提供了arguments
對象。這是一個類似數組的對象(不是完整的數組),它存儲在調用函數時傳遞給函數的值。
嘗試使用箭頭函數實現此功能:
// 函数声明 function sayHiStranger() { return 'Hi, stranger!' } // 调用函数 sayHiStranger()
當您調用該函數時,您將收到以下錯誤消息:Uncaught ReferenceError: arguments is not defined。這意味著arguments
對像在箭頭函數中不可用。事實上,將箭頭函數替換為常規函數可以解決問題:
const sayHiStranger = function () { return 'Hi, stranger!' }
因此,如果您需要arguments
對象,則不能使用箭頭函數。
但是,如果您真的想使用箭頭函數來複製相同的功能呢?您可以做的一件事是使用ES6剩餘參數(...)。以下是如何重寫您的函數:
const sayHiStranger = () => 'Hi, stranger'
通過使用箭頭函數,您可以編寫簡潔的一行代碼,使用隱式返回,並最終忘記使用舊方法來解決JavaScript中this
關鍵字的綁定問題。箭頭函數也與.map()
、.sort()
、.forEach()
、.filter()
和.reduce()
等數組方法配合得很好。但請記住:箭頭函數不會替換常規JavaScript函數。請記住,只有在箭頭函數是正確的工具時才使用它們。
如果您對箭頭函數有任何疑問,或者需要任何幫助來正確使用它們,我建議您訪問SitePoint友好的論壇。那裡有很多知識淵博的程序員隨時準備提供幫助。
您可以使用以下語法定義箭頭函數:(參數)=>表達式。例如:(x,y)=>x y定義一個箭頭函數,該函數接受兩個參數並返回它們的和。
您可以使用以下語法定義箭頭函數:(參數)=>表達式。例如:(x,y)=>x y定義一個箭頭函數,該函數接受兩個參數並返回它們的和。
箭頭函數與常規函數在以下幾個方面有所不同:
它們沒有自己的this
。相反,它們繼承周圍詞法作用域的this
值。
箭頭函數不能用作構造函數,這意味著您不能使用new
創建對象的實例。
箭頭函數沒有自己的arguments
對象。相反,它們繼承封閉作用域的arguments
。
箭頭函數更簡潔,更適合簡單的單行操作。
箭頭函數提供簡潔的語法,使您的代碼更具可讀性。它們還有助於避免this
綁定的問題,因為它們繼承周圍的上下文。這可以簡化某些編碼模式並減少對bind
、apply
或call
等變通方法的需求。
雖然箭頭函數對許多場景很有用,但它們可能並不適用於所有情況。它們最適合短小簡單的函數。對於復雜的函數或需要其自身this
上下文的函數,傳統函數可能更合適。
箭頭函數是在ECMAScript 6(ES6)中引入的,並受現代瀏覽器和Node.js版本支持。它們廣泛用於現代JavaScript開發中。
箭頭函數不能用作構造函數,沒有自己的arguments
對象,並且不太適合需要動態this
上下文的方法。此外,它們的簡潔語法可能不適合包含多個語句的函數。
是的,箭頭函數可以用於對像或類中的方法。但是,請記住,箭頭函數沒有自己的this
,因此它們在需要動態this
上下文的方法中可能不會按預期工作。
當直接從箭頭函數返回對象字面量時,需要將對象括在括號中,以避免與函數塊混淆。例如:() => ({ key: value })。
是的,如果箭頭函數接受單個參數,則可以省略參數周圍的括號。例如,x => x * 2是一個有效的箭頭函數。
以上是箭頭在JavaScript中的功能:脂肪與簡潔語法的詳細內容。更多資訊請關注PHP中文網其他相關文章!