前言:es6箭頭函數沒出現之前,this的指向不是函數被建立時綁定,而是被怎麼樣的方式調用時綁定的。而箭頭函數剛好相反,箭頭函數的this指向是函數被建立時綁定的,它的指向就是目前詞法作用域中的this,并且不會因為被怎麼樣的方式調用改變綁定。
如果對非箭頭函數this指向有問題的朋友,建議看我之前的文章。【JavaScript】this的指向詳解
(為了展示友善,這兩個例子都是在浏覽器環境中運作,是以全局對象是window)
一、例子①
//這裡隻能用var定義變量,let,const定義的變量,不是綁定在window下。
var str = 'window';
const obj = {
str:'obj',
nativeFn: function(){
console.log(this.str, '目前詞法作用域中的this');
return function(){
console.log('原生函數',this.str);
}
},
arrowFn: function(){
console.log(this.str, '目前詞法作用域中的this');
return ()=>{
console.log('箭頭函數',this.str);
}
}
};
const obj2 = {
str:'obj2'
}
var nativeFn = obj.nativeFn();
var arrowFn = obj.arrowFn();
console.log('函數調用一 **********');
nativeFn();
arrowFn();
console.log('函數調用二 **********');
nativeFn.call(obj2);
arrowFn.call(obj2);
console.log('函數調用三 **********');
setTimeout(function(){
nativeFn();
arrowFn();
},50);
//函數調用四
var doc = document.documentElement;
doc.str = 'document';
doc.addEventListener('click',function(){
console.log('函數調用四 **********');
},false);
doc.addEventListener('click',nativeFn,false);
doc.addEventListener('click',arrowFn,false);
運作結果
通過運作結果可以發現, 無論我們怎麼改變箭頭函數arrowFn的調用方式,都不會改變this的指向,this始終指向它被建立時所處的詞法作用域中的this。
二、例子②
//這裡隻能用var定義變量,let,const定義的變量,不是綁定在window下。
var str = 'window';
const obj = {
str:'obj',
fn: ()=>{
console.log(this.str);
}
}
obj.fn();
運作結果
這時候this竟然指向了window對象,這也是使很多剛接觸箭頭函數的朋友容易困惑的一個點。在看看下面的例子相信就能了解這個問題的原因了。
//這裡隻能用var定義變量,let,const定義的變量,不是綁定在window下。
var str = 'window';
const obj = {
str:'obj',
fn: ()=>{
console.log(this.str);
},
fn2: function(){
console.log(this.str, '目前詞法作用域中的this')
return {
str: 'newObj',
fn: ()=>{
console.log(this.str);
}
}
}
}
obj.newFn = ()=>{
console.log(this.str);
}
obj.fn();
obj.newFn();
var newObj = obj.fn2();
newObj.fn();
運作結果
這裡已經不難看出來了,當我們建立對象的時候,是在全局作用域下建立的,而對象中的方法也是這時候建立的
(參照obj.newFn),
是以這時候的this是指向全局的,而我們在fn2裡面建立的對象,這個對象的方法的this就指向他被建立時的詞法作用域obj了。