1. 程式人生 > 程式設計 >JS什麼場景不適合箭頭函式

JS什麼場景不適合箭頭函式

概述

這些年來,ES6 將js的可用性提升到一個新的水平時: 箭頭函式、類等等,這些都很棒。

箭頭函式是最有價值的新功能之一,有很多好文章描述了它的上下文透明性和簡短的語法。

但每個事務都有兩面。通常,新特性會帶來一些混亂,其中之一就是箭頭函式被誤導了。本文將介紹一些場景,在這些場景中,你應該繞過箭頭函式,轉而使用良好的舊函式表示式或較新的簡寫語法。並且要注意縮短程式碼,因為這會影響程式碼的可讀性。

程式設計客棧義物件上的方法

在js中,方法是儲存在物件屬性中的函式。當呼叫該方法時,this將指向該方法所屬的物件。

Object literal

由於箭頭函式語法簡短,所以使用它來定義方法是很有吸引力的,讓咱們來試一試:

const calculate = {
  array: [1,2,3],sum: () => {
    console.log(this === window); // => true
    return this.array.reduce((result,item) => result + item);
  }
};
console.log(this === window); // => true
// Throws "TypeError: Cannot read property 'reduce' of undefined"
calculate.sum();

calculate.sum方法用箭頭函式定義。 但是在呼叫時,calculate.sum()會丟擲一個TypeError,因為this.array為undefKoxKFyWc

ined。

當呼叫calculate物件上的方法sum()時,上下文仍然是window。之所以會發生這種情況,是因為箭頭函式按詞法作用域將上下文繫結到window物件。

執行this.array等同於window.array,它是undefined。

解決方法是使用常規函式表示式來定義方法。 this 是在呼叫時確定的,而不是由封閉的上下文決定的,來看看修復後的版本:

const calculate = {  
  array: [1,sum() {
    console.log(this === calculate); // => true
    return this.array.reduce((result,item) => result + item);
  }
};
calculate.sum(); // => 6

因為sum是常規函式,所以在呼叫calculate.sum()時this是calculate物件。this.array是陣列引用,因此正確計算元素之和:6。

Object prototype

同樣的規則也適用於在原型物件上定義方法。使用一個箭頭函式來定義sayCatName方法,this指向window

function MyCat(name) {
  this.catName = name;
}
MyCat.prototype.sayCatName = () => {
  console.log(this === window); // => true
  return this.catName;
};
const cat = new MyCat('Mew');
cat.sayCatName(); // => undefined

使用早期的方式定義函式表示式:

function MyCat(name) {
  this.catName = name;
}
MyCat.prototype.sayCatName = function() {
  console.log(this === cat); // => true
  return this.catName;
};
const cat = new MyCat('Mew');
cat.sayCatName(); // => 'Mew'

sayCatName常規函式在作為方法呼叫時將上下文更改為cat物件:cat.sayCatName()。

動態上下文的回撥函式

this在JS中是一個強大的特性,它允許根據呼叫函式的方式更改上下文。通常,上下文是呼叫發生的目標物件,這使得程式碼更加自然,就像這個物件發生了什麼。

但是,箭頭函式會在宣告上靜態繫結上下文,並且無法使其動態化,但這種方式有壞也有好,有時候我們需要動態繫結。

在客戶端程式設計中,將事件偵聽器附加到DOM元素是一項常見的任務。事件觸發處理程式函式,並將this作為目標元素,這裡如果使用箭頭函式就不夠靈活。

下面的示例嘗試為這樣的處理程式使用箭頭函式:

const button = document.getElementById('myButton');
button.addEventListener('click',() => {
  console.log(this === window); // => true
  this.innerhtml = 'Clicked button';
});

在全域性上下文中this指向window。 當發生單擊事件時,瀏覽器嘗試使用按鈕上下文呼叫處理函式,但箭頭函式不會更改其預定義的上下文。this.innerhtml相當於window.innerHTML,沒有任何意義。

必須應用函式表示式,該表示式允許根據目標元素更改this:

const button = document.getElementById('myButton');
button.addEventListener('click',function() {
  console.log(this === button); // => true
  this.innerHTML = 'Clicked button';
});

當用戶單擊按鈕時,處理程式函式中的this指向button。因此這個問題。innerHTML = 'Clicked button'正確地修改按鈕文字以反映已單擊狀態。

呼叫建構函式

this在構造呼叫中是新建立的物件。當執行new MyFunction()時,建構函式MyFunction的上下文是一個新物件:this instanceof MyFunction === true。

注意,箭頭函式不能用作建構函式。javascript通過丟擲異常隱式阻止這樣做。

無論如何,this是來自封閉上下文的設定,而不是新建立的物件。換句話說,箭頭函式建構函式呼叫沒有意義,而且是模糊的。

讓我們看看如果嘗試這樣做會發生什麼:

const Message = (text) => {
  this.text = text;
};
// Throws "TypeError: Message is not a constructor"
const helloMessage = new Message('Hello World!');

執行new Message('Hello World!'),其中Message是一個箭頭函式,javaScript丟擲一個TypeError錯誤,Message不能用作建構函式。

上面的例子可以使用函式表示式來修復,這是建立建構函式的正確方法(包括函式宣告):

const Message = function(text) {
  this.text = text;
};
const helloMessage = new Message('Hello World!');

簡寫語法

箭頭函式有一個很好的屬性,它可以省略引數圓括號()、塊大括號{},如果函式主體只有一條語句,則返回。這有助於編寫非常短的函式。

原文作者的大學程式設計教授給學生一個有趣的任務:編寫 用C語言計算字串長度的最短函式,這是學習和探索新語言的好方式。

然而,在實際應用程式中,許多開發人員都會閱讀程式碼。 http://www.cppcns.com最短的語法並不總是適合幫助你的同事即時瞭解該方法的用途。

在某種程度上,簡寫的函式變得難以閱讀,所以儘量不要過度使用。讓各位們看一個例子

const multiply = (a,b) => b === undefined ? b => a * b : a * b;
const double = multiply(2);
double(3);      // => 6
multiply(2,3); // => 6

multiply返回兩個數字的乘法結果或與第一個引數繫結的閉包,以便以後的乘法運算。

該函式執行良好,看起來很短。但從一開始就很難理解它是做什麼的。

為了使其更具可讀性,可以從箭頭函式恢復可選花括號和return語句,或使用常規函式:

function multiply(a,b) {
  if (b === undefined) {
    return function(b) {
      returKoxKFyWcn a * b;
   KoxKFyWc }
  }
  return a * b;
}
const double = multiply(2);
double(3);      // => 6
multiply(2,3); // => 6

在簡短和冗長之間找到一個平衡點是很好的,這樣可以使程式碼更加直觀。

總結

毫無疑問,箭頭函式是一個很好的補充。當正確使用時,它會使前面必須使用.bind()或試圖捕獲上下文的地方變得簡單,它還簡化了程式碼。

某些情況下的優點會給其他情況帶來不利。 當需要動態上下文時,不能使用箭頭函式:定義方法,使用建構函式建立物件,在處理事件時從this獲取目標。

以上就是JS什麼場景不適合箭頭函式的詳細內容,更多關於JS的資料請關注我們其它相關文章!