JavaScript:學習筆記(5)——箭頭函數=>以及實踐
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
, call
和apply
。setInterval
只是一個普通的函數。實際上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;
最後總結兩點就是
- 箭頭函數寫代碼擁有更加簡潔的語法;
- 不會綁定
this
。
JavaScript:學習筆記(5)——箭頭函數=>以及實踐