ES6,箭頭函數 (=>)注意點


  1. 函數體內的this對象,就是定義時所在的對象,而不是使用時所在的對象。
  2. 不可以當作構造函數,也就是說,不可以使用new命令,否則會拋出一個錯誤。
  3. 不可以使用arguments對象,該對象在函數體內不存在。如果要用,可以用 rest 參數代替。
  4. 不可以使用yield命令,因此箭頭函數不能用作 Generator 函數。

上面四點中,第一點尤其值得注意。this對象的指向是可變的,但是在箭頭函數中,它是固定的。

var id = 21;

function foo() {
  setTimeout(function() {
    console.log('id:', this.id);
  }, 100);
}

function foo1() {
  setTimeout(() => {
    console.log('id:', this.id);
  }, 100);
}

foo.call({ id: 42 });// 21 普通函數 foo函數中this指向window
foo1.call({id:42});// 42 箭頭函數 foo1函數中this指向{id:42}對象

箭頭函數可以讓setTimeout里面的this,綁定定義時所在的作用域,而不是指向運行時所在的作用域。下面是另一個例子。

function Timer() { // 構造函數不能使用 箭頭函數
  this.s1 = 0;
  this.s2 = 0;
  // 箭頭函數
  setInterval(() => this.s1++, 1000);
  // 普通函數
  setInterval(function () {
    this.s2++;
  }, 1000);
}

var timer = new Timer();

setTimeout(() => console.log('s1: ', timer.s1), 3100); 
setTimeout(() => console.log('s2: ', timer.s2), 3100);
// s1: 3
// s2: 0

上面代碼中,Timer函數內部設置了兩個定時器,分別使用了箭頭函數和普通函數。前者的this綁定定義時所在的作用域(即Timer函數),后者的this指向運行時所在的作用域(此例是window,普通函數中this.s2即為window.s2==undefined)。所以,3100 毫秒之后,timer.s1被更新了 3 次,而timer.s2一次都沒更新。

箭頭函數的不適用點:

由於箭頭函數使得this從“動態”變成“靜態”,下面兩個場合不應該使用箭頭函數。

1.第一個場合是定義對象的方法,且該方法內部包括this。

const cat = {
  lives: 9,
  jumps: () => {
    this.lives--;
  }
}

上面代碼中,cat.jumps()方法是一個箭頭函數,這是錯誤的。調用cat.jumps()時,如果是普通函數,該方法內部的this指向cat;如果寫成上面那樣的箭頭函數,使得this指向全局對象,因此不會得到預期結果。
2.第二個場合是需要動態this的時候,也不應使用箭頭函數。

var button = document.getElementById('press');
button.addEventListener('click', () => {
  this.classList.toggle('on');
});

上面代碼運行時,點擊按鈕會報錯,因為button的監聽函數是一個箭頭函數,導致里面的this就是全局對象。如果改成普通函數,this就會動態指向被點擊的按鈕對象。

另外,如果函數體很復雜,有許多行,或者函數內部有大量的讀寫操作,不單純是為了計算值,這時也不應該使用箭頭函數,而是要使用普通函數,這樣可以提高代碼可讀性。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM