箭頭函數(shù)就是個(gè)簡(jiǎn)寫形式的函數(shù)表達(dá)式锹雏,并且它擁有詞法作用域的this值(即不會(huì)新產(chǎn)生自己作用域下的this, arguments, super
和new.target
等對(duì)象)。此外赞弥,箭頭函數(shù)總是匿名的店读。
箭頭函數(shù)的引入有兩個(gè)方面的影響:一是更簡(jiǎn)短的函數(shù)書寫纫普,而是對(duì) this 的詞法解析嫁艇。
更短的函數(shù)
在一些函數(shù)式編程模式里朗伶,更短的函數(shù)書寫方式很受歡迎。試比較:
var a = [
"Hydrogen",
"Helium",
"Lithium",
"Beryl-lium"
];
var a2 = a.map(function(s){ return s.length });
var a3 = a.map( s => s.length );
不綁定 this
在箭頭函數(shù)出現(xiàn)之前步咪,每個(gè)新定義的函數(shù)都有其自己的 this 值(例如论皆,構(gòu)造函數(shù)的 this 指向了一個(gè)新的對(duì)象;嚴(yán)格模式下的函數(shù)的 this 值為 undefined猾漫;如果函數(shù)是作為對(duì)象的方法被調(diào)用的点晴,則其 this 指向了那個(gè)調(diào)用他的對(duì)象)。在面向?qū)ο箫L(fēng)格的辦成中悯周,這杯證明是非常惱人的事情粒督。
function Person() {
// 構(gòu)造函數(shù) Person() 定義的 `this` 就是新實(shí)例對(duì)象自己
this.age = 0;
setInterval(function growUp() {
// 在非嚴(yán)格模式下,growUp() 函數(shù)定義了其內(nèi)部的 `this`
// 為全局對(duì)象, 不同于構(gòu)造函數(shù)Person()的定義的 `this`
this.age++;
}, 1000);
}
var p = new Person();
在 ECMAScript 3/5 中禽翼,這個(gè)問(wèn)題可以通過(guò)新增一個(gè)變量來(lái)指向期望的 this 對(duì)象屠橄,然后將該變量放到閉包中來(lái)解決。
function Person() {
var self = this; // 也有人選擇使用 `that` 而非 `self`.
// 只要保證一致就好.
self.age = 0;
setInterval(function growUp() {
// 回調(diào)里面的 `self` 變量就指向了期望的那個(gè)對(duì)象了
self.age++;
}, 1000);
}
除此之外闰挡,還可以使用bind函數(shù)锐墙,把期望的this值傳遞給 growUp()函數(shù)。
箭頭函數(shù)則會(huì)捕獲其所在上下文的this值长酗,作為自己的this值溪北,因此下面的額代碼將如期運(yùn)行。
function Person(){
this.age = 0;
setInterval(() => {
this.age++; // |this| 正確地指向了 person 對(duì)象
}, 1000);
}
var p = new Person();
與 strict mode 的關(guān)系
考錄到 this 是詞法層面上的夺脾,嚴(yán)格模式中與 this 相關(guān)的規(guī)則都將被忽略之拨。
var f = () => {'use strict'; return this};
f() === window; // 或全局對(duì)象
使用 call 或 apply 調(diào)用
由于 this 已經(jīng)在此法層面完成了綁定,通過(guò) call() 或 apply() 方法調(diào)用一個(gè)函數(shù)時(shí)咧叭,只是傳入了參數(shù)而已敦锌,對(duì) this 并沒(méi)有什么影響:
var adder = {
base : 1,
add : function(a) {
var f = v => v + this.base;
return f(a);
},
addThruCall: function(a) {
var f = v => v + this.base;
var b = {
base : 2
};
return f.call(b, a);
}
};
console.log(adder.add(1)); // 輸出 2
console.log(adder.addThruCall(1)); // 仍然輸出 2(而不是3 ——譯者注)
不綁定 arguments
將頭函數(shù)不會(huì)在其內(nèi)部爆出 arguments 對(duì)象:arguments.length, arguments[0], arguments[1] 等等,都不會(huì)指向箭頭函數(shù)的 arguments佳簸,而是指向了箭頭函數(shù)所在作用域的一個(gè)明為 argument 的值(如果有的活乙墙,否則,就是 undefined生均。)听想。
var arguments = 42;
var arr = () => arguments;
arr(); // 42
function foo() {
var f = () => arguments[0]; // foo's implicit arguments binding
return f(2);
}
foo(1); // 1
降頭函數(shù)沒(méi)有自己的 arguments 對(duì)象,不過(guò)在大多數(shù)情形下马胧, rest參數(shù)可以給出一個(gè)解決方案:
function foo() {
var f = (...args) => args[0];
return f(2);
}
foo(1); // 2
像方法一樣使用箭頭函數(shù)
如上所述汉买,箭頭函數(shù)表達(dá)式對(duì)沒(méi)有方法名的函數(shù)時(shí)最合適的,讓我們?cè)囍阉麄冏鳛榉椒〞r(shí)發(fā)生了什么佩脊。
'use strict';
var obj = {
i: 10,
b: () => console.log(this.i, this),
c: function() {
console.log( this.i, this)
}
}
obj.b(); // prints undefined, Window
obj.c(); // prints 10, Object {...}