1. 程式人生 > >JavaScript:學習筆記(5)——箭頭函數=>以及實踐

JavaScript:學習筆記(5)——箭頭函數=>以及實踐

理論知識 你會 未定義 light 報錯 註意 改變 導致 div

JavaScript:學習筆記(5)——箭頭函數=>以及實踐

ES6標準新增了一種新的函數:Arrow Function(箭頭函數)。本文參考的鏈接如下:

  • MDN箭頭函數:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions
  • 廖雪峰箭頭函數:https://www.liaoxuefeng.com/wiki/.......
  • FunDebug的文章:https://blog.fundebug.com/2017/05/25/arrow-function-for-beginner/

箭頭函數的理論知識

介紹

  箭頭函數表達式的語法比函數表達式更短,並且沒有自己的this,arguments,super或 new.target。這些函數表達式更適用於那些本來需要匿名函數的地方,並且它們不能用作構造函數

  箭頭函數相當於匿名函數,並且簡化了函數定義。箭頭函數有兩種格式,一種像下面這樣,只包含一個表達式,連{ ... }return都省略掉了

x => x * x

/*上面的箭頭函數相當於*/

function (x) {
    return x * x;
}

  還有一種可以包含多條語句,這時候就不能省略{ ... }return

x => {
    if (x > 0) {
        return x * x;
    }
    else {
        return - x * x;
    }
}

  如果要返回一個對象,就要註意,如果是單表達式,這麽寫的話會報錯:

// SyntaxError:
x => { foo: x }

  故返回對象時函數體的{ ... }有語法沖突,所以要改為({....})

// ok:
x => ({ foo: x })

  其語法結構可總結如下:

(參數1, 參數2, …, 參數N) => { 函數聲明 }
(參數1, 參數2, …, 參數N) => 表達式(單一)
//相當於:(參數1, 參數2, …, 參數N) =>{ return 表達式; }

// 當只有一個參數時,圓括號是可選的:
(單一參數) => {函數聲明}
單一參數 => {函數聲明}

// 沒有參數的函數應該寫成一對圓括號。
() => {函數聲明}
//加括號的函數體返回對象字面表達式:
參數=> ({foo: bar})

//支持剩余參數和默認參數
(參數1, 參數2, ...rest) => {函數聲明}
(參數1 = 默認值1,參數2, …, 參數N = 默認值N) => {函數聲明}

//同樣支持參數列表解構
let f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c;
f();  // 6

關於this

  和一般的函數不同,箭頭函數不會綁定this。 或則說箭頭函數不會改變this本來的綁定
  我們用一個例子來說明:

function Counter() {
  this.num = 0;
}
var a = new Counter();  

  因為使用了關鍵字new構造,Count()函數中的this綁定到一個新的對象,並且賦值給a。通過console.log打印a.num,會輸出0。即

console.log(a.num);
// 0

  如果我們想每過一秒將a.num的值加1,該如何實現呢?可以使用setInterval()函數。

function Counter() {
  this.num = 0;
  this.timer = setInterval(function add() {
    this.num++;
    console.log(this.num);
  }, 1000);
}

  我們來看一下輸出結果:

var b = new Counter();
// NaN
// NaN
// NaN
// ...

  你會發現,每隔一秒都會有一個NaN打印出來,而不是累加的數字。到底哪裏錯了呢?首先函數setInterval沒有被某個聲明的對象調用,也沒有使用new關鍵字,再之沒有使用bind, callapplysetInterval只是一個普通的函數。實際上setInterval裏面的this綁定到全局對象的。我們可以通過將this打印出來驗證這一點:

  回到之前的函數,之所以打印NaN,是因為this.num綁定到window對象的num,而window.num未定義

  那麽,我們如何解決這個問題呢?使用箭頭函數!使用箭頭函數就不會導致this被綁定到全局對象

function Counter() {
  this.num = 0;
  this.timer = setInterval(() => {
    this.num++;
    console.log(this.num);
  }, 1000);
}
var b = new Counter();
// 1
// 2
// 3
// ...

  通過Counter構造函數綁定的this將會被保留。在setInterval函數中,this依然指向我們新創建的b對象

  其實這裏也為了一個持續困擾我的問題,即是一種hack寫法。

var that = this;

最後總結兩點就是

  1. 箭頭函數寫代碼擁有更加簡潔的語法
  2. 不會綁定this

JavaScript:學習筆記(5)——箭頭函數=>以及實踐