天天看點

ES6中的箭頭函數=>this

ES6标準新增了一種新的函數:Arrow Function(箭頭函數)。為什麼叫Arrow Function?因為它的定義用的就是一個箭頭:

x => x * x      

相當于:

function(x){
  return x*x;
}      

箭頭函數相當于匿名函數,并且簡化了函數定義。

箭頭函數表達式的文法比函數表達式更簡潔,并且沒有自己的this,arguments,super或new.target。箭頭函數表達式更适用于那些本來需要匿名函數的地方,并且它不能用作構造函數。

箭頭函數有兩種格式,一種像上面的,隻包含一個表達式,連{ … }和return都省略掉了。還有一種可以包含多條語句,這時候就不能省略{ … }和return:

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

如果參數不是一個,就需要用括号()括起來:

// 兩個參數:
(x, y) => x * x + y * y

// 無參數:
() => 3.14

// 可變參數:
(x, y, ...rest) => {
    var i, sum = x + y;
    for (i=0; i<rest.length; i++) {
        sum += rest[i];
    }
    return sum;
}      

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

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

因為和函數體的{ … }有文法沖突,是以要改為:

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

this

箭頭函數看上去是匿名函數的一種簡寫,但實際上,箭頭函數和匿名函數有個明顯的差別:箭頭函數内部的this是詞法作用域,由上下文确定。

回顧前面的例子,由于JavaScript函數對this綁定的錯誤處理,下面的例子無法得到預期結果:

var obj = {
    birth: 1990,
    getAge: function () {
        var b = this.birth; // 1990
        var fn = function () {
            return new Date().getFullYear() - this.birth; // this指向window或undefined
        };
        return fn();
    }
};      

現在,箭頭函數完全修複了this的指向,this總是指向詞法作用域,也就是外層調用者obj:

var obj = {
    birth: 1990,
    getAge: function () {
        var b = this.birth; // 1990
        var fn = () => new Date().getFullYear() - this.birth; // this指向obj對象
        return fn();
    }
};
obj.getAge(); // 25      

更多箭頭函數示例如下:

// 空的箭頭函數傳回 undefined
let empty = () => {};

(() => 'foobar')(); 
// Returns "foobar"
// (這是一個立即執行函數表達式,可參閱 'IIFE'術語表) 


var simple = a => a > 15 ? 15 : a; 
simple(16); // 15
simple(10); // 10

let max = (a, b) => a > b ? a : b;

// Easy array filtering, mapping, ...

var arr = [5, 6, 13, 0, 1, 18, 23];

var sum = arr.reduce((a, b) => a + b);  
// 66

var even = arr.filter(v => v % 2 == 0); 
// [6, 0, 18]

var double = arr.map(v => v * 2);       
// [10, 12, 26, 0, 2, 36, 46]

// 更簡明的promise鍊
promise.then(a => {
  // ...
}).then(b => {
  // ...
});

// 無參數箭頭函數在視覺上容易分析
setTimeout( () => {
  console.log('I happen sooner');
  setTimeout( () => {
    // deeper code
    console.log('I happen later');
  }, 1);
}, 1);


var simple = a => a > 15 ? 15 : a;
simple(16); // 15
simple(10); // 10

let max = (a, b) => a > b ? a : b;      

繼續閱讀