溫馨提示×

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

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

詳解JS箭頭函數(shù)和常規(guī)函數(shù)

發(fā)布時(shí)間:2020-07-21 14:55:35 來(lái)源:億速云 閱讀:189 作者:小豬 欄目:web開(kāi)發(fā)

小編這次要給大家分享的是詳解JS箭頭函數(shù)和常規(guī)函數(shù),文章內(nèi)容豐富,感興趣的小伙伴可以來(lái)了解一下,希望大家閱讀完這篇文章之后能夠有所收獲。

本文實(shí)例講述了JS箭頭函數(shù)和常規(guī)函數(shù)之間的區(qū)別。分享給大家供大家參考,具體如下:

在 JavaScript 中,你可以通過(guò)多種方式去定義函數(shù)。

第一種常用的方法是使用關(guān)鍵字 function

// 函數(shù)聲明
function greet(who) {
 return `Hello, ${who}!`;
}
// 函數(shù)表達(dá)式
const greet = function(who) {
 return `Hello, ${who}`;
}

代碼中的函數(shù)聲明和函數(shù)表達(dá)式被稱為“常規(guī)函數(shù)”。

從 ES2015 開(kāi)始,第二種可用的方法是 箭頭函數(shù) 語(yǔ)法:

const greet = (who) => {
 return `Hello, ${who}!`;
}

雖然兩者的語(yǔ)法都能夠定義函數(shù),但是在開(kāi)發(fā)時(shí)該怎么選擇呢?這是個(gè)好問(wèn)題。

在本文中,我將展示兩者之間的主要區(qū)別,以供你能夠根據(jù)需要選擇正確的語(yǔ)法。

1. this

1.1常規(guī)函數(shù)

在常規(guī) JavaScript 函數(shù)內(nèi)部,this 值(即執(zhí)行上下文)是動(dòng)態(tài)的。

動(dòng)態(tài)上下文意味著 this 的值取決于如何調(diào)用函數(shù)。在 JavaScript 中,有 4 種調(diào)用常規(guī)函數(shù)的方式。

簡(jiǎn)單調(diào)用過(guò)程中,this 的值等于全局對(duì)象(如果函數(shù)在嚴(yán)格模式下運(yùn)行,則為 undefined ):

function myFunction() {
 console.log(this);
}

// 簡(jiǎn)單調(diào)用
myFunction(); // logs global object (window)

方法調(diào)用過(guò)程中,this 的值是擁有該方法的對(duì)象:

const myObject = {
 method() {
  console.log(this);
 }
};
// 方法調(diào)用
myObject.method(); // logs "myObject"

在使用 myFunc.call(context, arg1, ..., argN)myFunc.apply(context, [arg1, ..., argN]) 的間接調(diào)用中,this 的值等于第一個(gè)參數(shù):

function myFunction() {
 console.log(this);
}

const myContext = { value: 'A' };

myFunction.call(myContext); // logs { value: 'A' }
myFunction.apply(myContext); // logs { value: 'A' }

在使用關(guān)鍵字 new 的構(gòu)造函數(shù)調(diào)用期間,this 等于新創(chuàng)建的實(shí)例:

function MyFunction() {
 console.log(this);
}

new MyFunction(); // logs an instance of MyFunction
1.2箭頭函數(shù)

箭頭函數(shù)中 this 的行為與常規(guī)函數(shù)的 this 行為有很大不同。

無(wú)論如何執(zhí)行或在何處執(zhí)行,箭頭函數(shù)內(nèi)部的 this 值始終等于外部函數(shù)的 this 值。換句話說(shuō),箭頭函數(shù)可按詞法解析 this,箭頭函數(shù)沒(méi)有定義自己的執(zhí)行上下文。

在以下示例中,myMethod() 是箭頭函數(shù) callback() 的外部函數(shù):

const myObject = {
 myMethod(items) {
  console.log(this); // logs "myObject"  
  const callback = () => {
   console.log(this); // logs "myObject"  
  };
  items.forEach(callback);
 }
};

myObject.myMethod([1, 2, 3]); 

箭頭函數(shù) callback() 中的 this 值等于外部函數(shù) myMethod()this。

this 詞法解析是箭頭函數(shù)的重要功能之一。在方法內(nèi)部使用回調(diào)時(shí),要確保箭頭函數(shù)沒(méi)有定義自己的 this:不再有 const self = this 或者 callback.bind(this) 這種解決方法。

2.構(gòu)造函數(shù)

2.1 常規(guī)函數(shù)

如上一節(jié)所述,常規(guī)函數(shù)可以輕松的構(gòu)造對(duì)象。

例如用 Car() 函數(shù)創(chuàng)建汽車的實(shí)例:

function Car(color) {
 this.color = color;
}

const redCar = new Car('red');
redCar instanceof Car; // => true

Car 是常規(guī)函數(shù),使用關(guān)鍵字 new 調(diào)用時(shí)會(huì)創(chuàng)建 Car 類型的新實(shí)例。

2.2 箭頭函數(shù)

this 詞法解決了箭頭函數(shù)不能用作構(gòu)造函數(shù)。

如果你嘗試調(diào)用帶有 new 關(guān)鍵字前綴的箭頭函數(shù),則 JavaScript 會(huì)引發(fā)錯(cuò)誤:

const Car = (color) => {
 this.color = color;
};

const redCar = new Car('red'); // TypeError: Car is not a constructor 

調(diào)用 new Car('red')(其中 Car 是箭頭函數(shù))會(huì)拋出 TypeError: Car is not a constructor

3. arguments 對(duì)象

3.1 常規(guī)函數(shù)

在常規(guī)函數(shù)的主體內(nèi)部,arguments 是一個(gè)特殊的類似于數(shù)組的對(duì)象,其中包含被調(diào)用函數(shù)的參數(shù)列表。

讓我們用 3 個(gè)參數(shù)調(diào)用 myFunction 函數(shù):

function myFunction() {
 console.log(arguments);
}

myFunction('a', 'b'); // logs { 0: 'a', 1: 'b'}

類似于數(shù)組對(duì)象的 arguments 中包含調(diào)用參數(shù):'a''b'。

3.2箭頭函數(shù)

另一方面,箭頭函數(shù)內(nèi)部未定義 arguments 特殊關(guān)鍵字。

用詞法解析 arguments 對(duì)象:箭頭函數(shù)從外部函數(shù)訪問(wèn) arguments。

讓我們?cè)囍诩^函數(shù)內(nèi)部訪問(wèn) arguments

function myRegularFunction() {
 const myArrowFunction = () => {  
   console.log(arguments); 
 }
 myArrowFunction('c', 'd');
}

myRegularFunction('a', 'b'); // logs { 0: 'a', 1: 'b' }

箭頭函數(shù) myArrowFunction() 由參數(shù) 'c', 'd' 調(diào)用。在其主體內(nèi)部,arguments 對(duì)象等于調(diào)用 myRegularFunction() 的參數(shù): 'a', 'b'

如果你想訪問(wèn)箭頭函數(shù)的直接參數(shù),可以使用剩余參數(shù) ...args

function myRegularFunction() {
 const myArrowFunction = (...args) => {  
   console.log(args); 
 }
 myArrowFunction('c', 'd');
}

myRegularFunction('a', 'b'); // logs { 0: 'c', 1: 'd' }

剩余參數(shù) ... args 接受箭頭函數(shù)的執(zhí)行參數(shù):{ 0: 'c', 1: 'd' }。

4.隱式返回

4.1常規(guī)函數(shù)

使用 return expression 語(yǔ)句從函數(shù)返回結(jié)果:

function myFunction() {
 return 42;
}

myFunction(); // => 42

如果缺少 return 語(yǔ)句,或者 return 語(yǔ)句后面沒(méi)有表達(dá)式,則常規(guī)函數(shù)隱式返回 undefined

function myEmptyFunction() {
 42;
}

function myEmptyFunction2() {
 42;
 return;
}

myEmptyFunction(); // => undefined
myEmptyFunction2(); // => undefined
4.2箭頭函數(shù)

可以用與常規(guī)函數(shù)相同的方式從箭頭函數(shù)返回值,但有一個(gè)有用的例外。

如果箭頭函數(shù)包含一個(gè)表達(dá)式,而你省略了該函數(shù)的花括號(hào),則將顯式返回該表達(dá)式。這些是內(nèi)聯(lián)箭頭函數(shù)

const increment = (num) => num + 1;

increment(41); // => 42

increment() 僅包含一個(gè)表達(dá)式:num + 1。該表達(dá)式由箭頭函數(shù)隱式返回,而無(wú)需使用 return 關(guān)鍵字。

5. 方法

5.1 常規(guī)函數(shù)

常規(guī)函數(shù)是在類上定義方法的常用方式。

在下面 Hero 類中,用了常規(guī)函數(shù)定義方法 logName()

class Hero {
 constructor(heroName) {
  this.heroName = heroName;
 }

 logName() {  console.log(this.heroName); }}

const batman = new Hero('Batman');

通常把常規(guī)函數(shù)用作方法。

有時(shí)你需要把該方法作為回調(diào)提供給 setTimeout() 或事件監(jiān)聽(tīng)器。在這種情況下,你可能會(huì)很難以訪問(wèn) this 的值。

例如用 logName() 方法作為 setTimeout() 的回調(diào):

setTimeout(batman.logName, 1000);
// after 1 second logs "undefined"

1 秒鐘后,undefined 會(huì)輸出到控制臺(tái)。 setTimeout()執(zhí)行 logName 的簡(jiǎn)單調(diào)用(其中 this 是全局對(duì)象)。這時(shí)方法會(huì)與對(duì)象分離。

讓我們手動(dòng)把 this 值綁定到正確的上下文:

setTimeout(batman.logName.bind(batman), 1000);
// after 1 second logs "Batman"

batman.logName.bind(batman)this 值綁定到 batman 實(shí)例?,F(xiàn)在,你可以確定該方法不會(huì)丟失上下文。

手動(dòng)綁定 this 需要樣板代碼,尤其是在你有很多方法的情況下。有一種更好的方法:把箭頭函數(shù)作為類字段。

5.2 箭頭函數(shù)

感謝類字段提案(目前在第3階段),你可以將箭頭函數(shù)用作類中的方法。

與常規(guī)函數(shù)相反,現(xiàn)在用箭頭定義的方法能夠把 this 詞法綁定到類實(shí)例。

讓我們把箭頭函數(shù)作為字段:

class Hero {
 constructor(heroName) {
  this.heroName = heroName;
 }

 logName = () => {  
   console.log(this.heroName); 
 }
}

const batman = new Hero('Batman');

現(xiàn)在,你可以把 batman.logName 用于回調(diào)而無(wú)需手動(dòng)綁定 thislogName() 方法中 this 的值始終是類實(shí)例:

setTimeout(batman.logName, 1000);
// after 1 second logs "Batman"

6. 總結(jié)

了解常規(guī)函數(shù)和箭頭函數(shù)之間的差異有助于為特定需求選擇正確的語(yǔ)法。

常規(guī)函數(shù)中的 this 值是動(dòng)態(tài)的,并取決于調(diào)用方式。是箭頭函數(shù)中的 this 在詞法上是綁定的,等于外部函數(shù)的 this。

常規(guī)函數(shù)中的 arguments 對(duì)象包含參數(shù)列表。相反,箭頭函數(shù)未定義 arguments(但是你可以用剩余參數(shù) ...args 輕松訪問(wèn)箭頭函數(shù)參數(shù))。

如果箭頭函數(shù)有一個(gè)表達(dá)式,則即使不用 return 關(guān)鍵字也將隱式返回該表達(dá)式。

最后一點(diǎn),你可以在類內(nèi)部使用箭頭函數(shù)語(yǔ)法定義去方法。粗箭頭方法將 this 值綁定到類實(shí)例。

不管怎樣調(diào)用胖箭頭方法,this 始終等于類實(shí)例,在回調(diào)這些方法用時(shí)非常有用。

看完這篇關(guān)于詳解JS箭頭函數(shù)和常規(guī)函數(shù)的文章,如果覺(jué)得文章內(nèi)容寫(xiě)得不錯(cuò)的話,可以把它分享出去給更多人看到。

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

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

AI