談談function函數和箭頭函數

聽雪落 2021-09-18 13:57:56 阅读数:834

function

前言

function函數和箭頭函數算是一個老生常談的問題了,從我剛接觸javaScript的時候就被告知,不要直接使用function,直接用箭頭函數,這樣能避免80%的問題,實際使用過程中也確實是這樣,在各種錯綜複雜的函數回調中,如果不使用箭頭函數,會導致this指向錯亂,程序各種報錯。(當然也可以使用call之類的Function函數去改變this指向,不够這樣大大加深了操作成本)

今年難得有空摸個魚就想來聊一聊這個話題,也幫自己理一下思路。

區別

function和箭頭函數最直觀的區別就是創建方法不同

// function函數創建
function A() {
console.log(this)
}
B = function () {
console.log(this)
}
// 箭頭函數創建
C = () => {
console.log(this)
}
複制代碼

接下來就是常說的this指向問題了,以下都是不考慮call、bind、apply的情况:

  • function函數的this是使用時指定。(創建function函數時,this是undefined,只有在函數被調用的時候,this指向調用者)
  • 箭頭函數的this是創建時指定。(當箭頭函數被創建的時候,會根據當前上下文來bind當前的this,函數在之後的調用過程中,都能訪問到創建該函數的上下文)

我們使用瀏覽器的控制臺進行調試

// 執行function A時,控制臺輸出this指向window
A()
// 執行objectB.b時,控制臺輸出this指向{b: ƒ}
objectB = { b: B }
objectB.b()
// 執行箭頭函數 C時,控制臺輸出this指向window
C()
// 執行objectC.c時,控制臺輸出this指向window
objectC = { c: C }
objectC.c()
複制代碼

上面的例子能很好的看出來,function函數的this指向它的調用者,而箭頭函數的this指向與調用者無關。

對象創建

我們明白在js裏,可以 new function函數來創建對象,但是不能 new 箭頭函數來創建對象。

// 使用 new function A 來創建對象,能得到繼承A的原型鏈的的一個新對象
new A()
// 報錯:Uncaught TypeError: C is not a constructor
new C()
複制代碼

為什麼同樣是函數,但是卻不能通過 new 箭頭函數來創建對象呢?

其實之前的例子可以看出,function函數是沒有指定對象的,根據js使用 new function函數來創建對象的規則(先創建空對象,用空對象執行function函數,然後該對象繼承function函數的原型鏈,最後返回該對象)不難看出,對於創建時就綁定了this指向的箭頭函數來說,是沒法使用new關鍵字來創建的。

雖然我們不能通過 new 箭頭函數來創建對象,但是我們可以通過後面完善的Object的Prototype函數來創建對象

// 用第一個對象參數,執行完箭頭函數後,該對象繼承function函數的原型鏈,最後返回該對象
Object.create({},C)
複制代碼

總結

不難看出,function函數的初衷就是為了創建對象,所以我們用function函數來當普通函數在web端調用的時候,很容易出現各種問題,而後面出現的箭頭函數極大的解决了這個問題。 所以,我建議在之後的代碼編寫中,當需要使用創建對象的時候,使用function函數,而僅僅需要當做執行方法時,用箭頭函數。這樣寫起代碼來思路很更加清晰。

後記

不過話說回來,現在有es6的語法,可以說,梭哈箭頭函數就行,把function函數丟進曆史的長河裏吧。(僅個人見解,求生欲極强)

版权声明:本文为[聽雪落]所创,转载请带上原文链接,感谢。 https://gsmany.com/2021/09/20210918135756155P.html