ES6 箭頭函數你正確使用了嗎

ES6 箭頭函數你正確使用了嗎

博客說明

文章所涉及的資料來自互聯網整理和個人總結,意在於個人學習和經驗匯總,如有什麼地方侵權,請聯繫本人刪除,謝謝!

說明

在ES6中允許使用「箭頭」(=>)定義函數,所以在我們後續寫代碼的過程中出現的很多的箭頭函數,因為真香!但是也帶來的一些問題,靈魂拷問,你真的了解箭頭函數嗎?因為不敢肯定作答,故此書。

箭頭函數

一個簡單箭頭函數
// es6
const hello = item => item;

// es5 上面的代碼等同於
const hello = function (item) {
  return item;
};
用法(三大如果)

如果箭頭函數不需要參數或需要多個參數,就使用一個圓括號代表參數部分。

const hello = () => 'hello';

const sum = (num1, num2) => num1 + num2;

如果箭頭函數的代碼塊部分多於一條語句,就要使用大括號將它們括起來,並且使用return語句返回。

const sum = (num1, num2) => { 
  let num = 0; 
  if(num1 && num2){
    num = num1 + num2;
  }
  return num;
}

如果箭頭函數直接返回一個對象,必須在對象外面加上括號,否則會報錯。

const getInfo = id => ({ id: id, name: "hello" });

四大注意點

以下四點可能被無數次的提及,並且出現在各大面試題當中,不錯,今天又來了一次。

  • 箭頭函數沒有自己的this對象
  • 不可以當作構造函數,不可以使用new命令
  • 不可以使用arguments對象,該對象在函數體內不存在。如果要用,可以用 rest 參數代替
  • 不可以使用yield命令,因此箭頭函數不能用作 Generator 函數

箭頭函數的this指向

對於普通函數來說,內部的this指向函數運行時所在的對象。箭頭函數沒有自己的this對象,內部的this就是定義時上層作用域中的this

箭頭函數內部的this指向是固定的,相比之下,普通函數的this指向是可變的。

將ES6轉成ES5

發現其實只是所謂的箭頭函數的this只是從外面」借「來的

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

// ES5
function foo() {
  var _this = this;

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

在setInterval中,其實是沒有this.s2的,所以它的值不會變化。

function test() {
  this.s1 = 0;
  this.s2 = 0;
  // 箭頭函數
  setInterval(() => this.s1++, 1000);
  // 普通函數
  setInterval(function () {
    this.s2++;
  }, 1000);
}

s1 // 1
s2 // 0

普通函數修改之後可以修改s2

// 普通函數
setInterval(function () {
	let _this = this;
  _this.s2++;
}, 1000);

在這裡也能看到箭頭函數的this的指向,可以發現箭頭函數非常適合來做回調

不能作為構造函數

不能作為構造函數,這個好理解。因為箭頭函數根本沒有自己的this,拿甚構造?所以箭頭函數也就不能用作構造函數。也不能使用new關鍵詞。

不可以使用arguments對象

像this一樣,arguments指向外層函數的對應變量,像類似的兄弟還有supernew.target

function hello() {
  setTimeout(() => {
    console.log('args:', arguments);
  }, 1000);
}

hello(1,2,3,4)
// args: [1, 2, 3, 4]

也因為這個this的問題,箭頭函數也不能用call()apply()bind()這些方法去改變this的指向,因此箭頭函數的this是」靜態「的。

箭頭函數的好與壞

說到箭頭函數的this,導致這個沒有那個沒有,其實不然,在ES6之前的this對象一直是一個令人頭痛的問題,使用時小心翼翼,回調一多,代碼就糊了。正是因為這個」靜態「的this的出現,改善了這一些問題。

在使用箭頭函數的時候,要合理的利用箭頭函數的優劣,選擇合適的場景。在定義對象方法和動態綁定this的時候不要使用箭頭函數。

感謝

萬能的網絡

阮一峰的ES6教程

以及勤勞的自己,個人博客GitHub

微信公眾號