少年,不要濫用箭頭函式啊

2022-03-07 19:21:26 字數 2933 閱讀 6831

箭頭函式是什麼?

箭頭函式沒有this

什麼情況下該使用箭頭函式

在es6大行其道的今天,不應用點es6特性似乎有些政治不正確。最近剛好有個node的專案,最低要支援到nodejs 4.0,在node.green看了下es6的支援度,我想使用的特性基本都有支援,遂決定在新專案中採用es6來寫。

當然第一件事情就是毫不留情地消滅var,專案中能用const的地方不用let,能用let的地方不用var。

第二件事情就是使用勞動人民喜聞樂見的箭頭函式替代function。當我心滿意足地看到滿屏的=>時,現實給了我一記響亮的耳光——改過之後的程式錯誤百出!

所以,當我們使用箭頭函式時,一定要搞清楚箭頭函式是什麼回事,適用於什麼場景。本文就針對以上問題來討論下箭頭函式。

箭頭函式的語法我就不講了,相信大家都見識過。跟我一樣,大家喜歡箭頭函式90%的原因是它好看。除了好看,它是不是與function等價呢?肯定不等價,因為tc39不可能僅因為好看而引入乙個語法糖(class除外)。

箭頭函式的淵源可以追溯到上古時期乙個叫lambda演算的東西。lambda演算是數學家提出來的,有些數學家跟我們程式設計師一樣也很懶,數學定理那麼多,今天要證三角定律,明天要證勾股定律,累不累!那能不能將所有的證明問題用乙個統一的體系進行形式化描述,然後由機器來完成自動推導呢?lambda演算就是幹這個的,圖靈也搞了一套體系叫圖靈機,兩者是等價的。

關於lambda演算說了這麼多,好像跟今天要講的箭頭函式沒什麼關係?其實是有關係的,lambda演算深刻影響了箭頭函式的設計。數學家們喜歡用純函式式程式語言,純函式的特點是沒有***,給予特定的輸入,總是產生確定的輸出,甚至有些情況下通過輸出能夠反推輸入。要實現純函式,必須使函式的執行過程不依賴於任何外部狀態,整個函式就像乙個數學公式,給定一套輸入引數,不管是在地球上還是火星上執行都是同乙個結果。

箭頭函式要實現類似純函式的效果,必須剔除外部狀態。所以當你定義乙個箭頭函式,在普通函式裡常見的thisargumentscaller是統統沒有的。

箭頭函式沒有this,那下面的**明顯可以取到this啊:

123

4567

8

function foo() 

foo() // 1

以上箭頭函式中的this其實是父級作用域中的this,即函式foothis。箭頭函式引用了父級的變數,構成了乙個閉包。以上**等價於:

123

4567

8910

function foo() 

foo() // 1

箭頭函式不僅沒有this,常用的arguments也沒有。如果你能獲取到arguments,那它一定是來自父作用域的。

123

45

function foo() 

foo(1, 2)(3, 4) // 1

上例中如果箭頭函式有arguments,就應該輸出的是3而不是1。

乙個經常犯的錯誤是使用箭頭函式定義物件的方法,如:

123456

let a = 

a.bar() //undefined

以上**中,箭頭函式中的this並不是指向a這個物件。物件a並不能構成乙個作用域,所以再往上到達全域性作用域,this就指向全域性作用域。如果我們使用普通函式的定義方法,輸出結果就符合預期,這是因為a.bar()函式執行時作用域繫結到了a物件。

123456

let a = 

}a.bar() // 1

另乙個錯誤是在原型上使用箭頭函式,如:

123

4567

8

function a() 

a.prototype.bar = () => console.log(this.foo)

let a = new a()

a.bar() //undefined

同樣,箭頭函式中的this不是指向a,而是根據變數查詢規則回溯到了全域性作用域。同樣,使用普通函式就不存在問題。

通過以上說明,我們可以看出,箭頭函式除了傳入的引數之外,真的是什麼都沒有!如果你在箭頭函式引用了thisarguments或者引數之外的變數,那它們一定不是箭頭函式本身包含的,而是從父級作用域繼承的。

到這裡,我們可以發現箭頭函式並不是萬金油,稍不留神就會踩坑。

至於什麼情況該使用箭頭函式,《you don』t know about js》給出了乙個決策圖:

以上決策圖看起來有點複雜,我認為有三點比較重要:

箭頭函式適合於無複雜邏輯或者無***的純函式場景下,例如用在mapreducefilter的**函式定義中;

不要在最外層定義箭頭函式,因為在函式內部操作this會很容易汙染全域性作用域。最起碼在箭頭函式外部包一層普通函式,將this控制在可見的範圍內;

如開頭所述,箭頭函式最吸引人的地方是簡潔。在有多層函式巢狀的情況下,箭頭函式的簡潔性並沒有很大的提公升,反而影響了函式的作用範圍的識別度,這種情況不建議使用箭頭函式。

請不要濫用異常

exception php的異常機制的功能非常強大,並且是可以跨作用域的傳遞豐富的資訊,但它強大的功能很容易讓我們濫用它。比如在使用者檢查登入時,如果密碼不正確,你可能會在模型中丟擲乙個異常,在控制器處理它。對於程式設計師,這樣做會很舒服,因為你不再費心思考慮心如何構建返回值和制定返回規範,也不必關...

不要濫用網路資源

網路資源很豐富,地球人都知道。但是,請不要濫用網路資源。如今,很多人遇到乙個技術問題,首先想到的是去 google 一下,看看有沒有現成的 solution 這樣做的後果是,大家的 solution 都一樣,缺乏創新。我覺得,當你遇到問題時,得先自己想一想,搞出乙個自己的 solution 這個so...

Linq TO SQL 雖好,但不要濫用

看看下面的例子。我們的場景是,需要對客戶表按照國家進行分組,然後列印出來每個國家的客戶數目。下面的語法看起來很優雅 using system using system.linq 客戶總數 item.key,item.count foreach var i in item 但是,注意觀察一下,每迴圈乙...