關(guān)于箭頭函數(shù)中this值的問題,網(wǎng)上查查,會告訴你 “箭頭函數(shù)的this固定化,箭頭函數(shù)中的this綁定定義時所在的作用域......”,好繞!
箭頭函數(shù)中this倒底指向誰?一句話,箭頭函數(shù)內(nèi)的this就是箭頭函數(shù)外的那個this! 為什么?因?yàn)榧^函數(shù)沒有自己的this。
如果你已明白這句話的意思,那么本文到此結(jié)束,你可以去看看別的更有營養(yǎng)的東西了。
如果我這句話描述的不清楚,或你對它有懷疑,請繼續(xù)往下看。如果說錯了請使勁拍磚。
查看原文
直接上代碼!
注:以下代碼全基于瀏覽器非嚴(yán)格模式運(yùn)行,且假定你已經(jīng)對非箭頭函數(shù)中的this全然了解
咱先定義一個全局變量a,后面所有的示例都假定此全局變量已存在:
var a = 0;
第一個示例:
// demo1
var obj = {
a: 1,
b1: this.a,
b2: () => this.a,
};
console.log(obj.b1); // 0
console.log(obj.b2()); // 0
根據(jù)結(jié)果可以看到obj對象中的屬性b1的值來自全局變量a,而不是obj對象的屬性a,也就是說b1: this.a,中的this指向window。而b2: () => this.a,中的this同樣指向window,返回全局變量a的值。
第二個示例:
// demo2
(function fn(){
var a = 2;
console.log(this.a); // 0
const subf = ()=>this.a;
console.log(subf()); // 0
})()
第三個示例:
// demo3
var obj2 = {
a: 3,
b1: function(){ return this.a;},
b2: function(){ return ()=>this.a},
};
console.log(obj2.b1()); // 3
console.log(obj2.b2()()); // 3
這個示例中箭頭函數(shù)外的this是哪個?我們在箭頭函數(shù)外面加個this.a看看:
var obj2 = {
a: 3,
b1: function(){ return this.a;},
b2: function(){ return this.a,()=>this.a},
};
console.log(obj2.b1()); // 3
console.log(obj2.b2()()); // 3
第四個示例:
// demo4
var obj3 = {
a: 4,
b1: function(){ return this.a;},
b2: function(){ return ()=> () => () => this.a},
};
console.log(obj4.b1()); // 4
console.log(obj4.b2()()()()); // 4
這里箭頭函數(shù)返回箭頭函數(shù)再返回箭頭函數(shù),最后一個箭頭函數(shù)返回this.a。這個this是誰?就是最后箭頭函數(shù)外面的外面的外面的那個this,也就是obj3.b1中的那個this,也就是obj3.a。:)
實(shí)情是這樣:箭頭函數(shù)沒有自己的this,所以不管嵌套多少層,都不影響this是誰。
第五個示例:
// demo5
function f0() {
var a = 5;
setTimeout(function() {
var b1 = this.a;
console.log(b1); // 0
}, 100);
setTimeout(function() {
var b2 = ()=> this.a;
console.log(b2()); // 0
}, 200);
}
f0(); // 0 0
我們都知道setTimeout中的那個function運(yùn)行于全局環(huán)境下,因此里面的this指向window。而箭頭函數(shù)沒有自己的this,所以第二個setTimeout中箭頭函數(shù)的this也指向window.
那么setTimeout的第一個參數(shù)使用箭頭函數(shù)會是個什么情況?看下一個示例。
第六個示例:
// demo6
function f1() {
console.log(this.a);
setTimeout(() => {
console.log(this.a);
}, 100);
}
f1(); // 0 0
這里箭頭函數(shù)作為setTimeout的第一個參數(shù),箭頭函數(shù)外面的那個this是誰?把箭頭函數(shù)換成this.fn():
function f1() {
console.log(this.a); // 0
setTimeout(this.fn() , 100);
}
我們這里不用了解this.fn()有什么功能,看到它我們就會明白了this.fn()中的this和前面一行中的this.a中的this是同一個this。
擴(kuò)展一下:
// 這樣執(zhí)行
f1.call({a: 7}); // 7 7
結(jié)果是輸出兩個7,
為什么?
// demo6
function f1() {
console.log(this.a); // 因?yàn)橥ㄟ^call對this的綁定,f1中的this指向 {a: 7}
setTimeout(() => {
console.log(this.a); // 同樣這里this指向 {a: 7}
}, 100);
}
同理:
var bindf1 = f1.bind({a: 8});
bindf1(); // 8 8
總結(jié)
箭頭函數(shù)沒有自己的this,箭頭函數(shù)中用this和普通語句中的this沒什么區(qū)別,所以,你知道非箭頭函數(shù)下怎么用this,就知道箭頭函數(shù)下怎么用this。
關(guān)于 “箭頭函數(shù)對this固定化,箭頭函數(shù)中的this綁定定義時所在的作用域,箭頭函數(shù)不能通過 call() 或 apply() 方法綁定this” 等描述,都源于箭頭函數(shù)沒有自己的this。