原文鏈接:http://www.itdecent.cn/p/c1ee12a328d2
常見(jiàn)的window屬性和方法有alter,document,parseInt,setTimeout,setInterval,localtion等等,這些在默認(rèn)的情況下是省略了window前綴的。(window.alter = alter),所以下文提到箭頭函數(shù)解決了匿名函數(shù)this指向的問(wèn)題(匿名函數(shù)的執(zhí)行環(huán)境具有全局性),包括setTimeout和setInterval中使用this所造成的問(wèn)題。
以下都是在非嚴(yán)格模式下討論
1.普通函數(shù)中的this
在JavaScript中,this是在函數(shù)執(zhí)行過(guò)程中自動(dòng)生成的一個(gè)內(nèi)部對(duì)象,指的就是當(dāng)前對(duì)象。
js的函數(shù)可以多層嵌套,如果內(nèi)層的想要獲得外層的this,可以定義一個(gè)變量?jī)?chǔ)存起來(lái)
var _this=this
在全局函數(shù)中,比如匿名函數(shù),this指向的是window。
例子:
var name=" the window";
var obj = {
name:'my obj',
getNameFun:function(){
return function(){
return this.name;
}
}
}
console.log(obj.getNameFun()());// the window
原因是,匿名函數(shù)的執(zhí)行環(huán)境是全局的,而且this只在函數(shù)內(nèi)部起作用。此時(shí)的this.name在匿名函數(shù)中找不到,所以就從全局中找,找到后打印出來(lái)。
上面的例子改寫(xiě)一下
var name=" the window";
var obj = {
name:'my obj',
getNameFun:function(){
var _this=this
return function(){
return _this.name;
}
}
}
console.log(obj.getNameFun()());//my obj
在getNameFun內(nèi)將this賦給_this,此時(shí)的_this指向的是掛載(調(diào)用)的對(duì)象,即為obj,在匿名函數(shù)中調(diào)用_this.name會(huì)在obj上查找相應(yīng)的數(shù)據(jù),就不會(huì)在全局上查找
函數(shù)的執(zhí)行對(duì)象放在window
function test(){
console.log(this);
}
test();//window
問(wèn)題:為啥是window,因?yàn)闆](méi)變量聲明?
關(guān)于setTimeout和setInterval的this指向問(wèn)題
var obj = {
func:function(){
console.log(this);
},
say:function(){
var that = this;
setTimeout(function(){
console.log(that)
});
}
}
obj.func();//obj
obj.say();//obj
把 var that = this;去掉
var obj = {
func:function(){
console.log(this);
},
say:function(){
setTimeout(function(){
console.log(that)
});
}
}
obj.func();//obj
obj.say();//window
問(wèn)題: setTimeout里執(zhí)行的函數(shù)為啥是window,因?yàn)閟etTimeout就是window下的方法
例子:
window.val = 1;
var obj = {
val:2,
dbl:function(){
this.val*=2;
val*=2;
console.log(this.val);
console.log(val);
}
}
obj.dbl();//4 2
var func = obj.dbl;
func();//8 8
執(zhí)行obj.dbl()時(shí),this.val的this指向obj內(nèi)的val=2;val在obj內(nèi)沒(méi)有定義所以從全局上找val=1,因此運(yùn)算結(jié)果為4 2
func的執(zhí)行對(duì)象是window,我們可以此時(shí)全局的val已經(jīng)等于4了,在經(jīng)過(guò)this.val=2,val=2的運(yùn)算,打印的結(jié)果就是8 8。
問(wèn)題:為啥執(zhí)行func,全局的val等于4,不是2?
2.ES6箭頭函數(shù)this
箭頭函數(shù)的this定義:箭頭函數(shù)的this是在定義函數(shù)時(shí)綁定的,不是在執(zhí)行過(guò)程中綁定的。簡(jiǎn)單的說(shuō),函數(shù)在定義時(shí),this就繼承了定義函數(shù)的對(duì)象。
所以,這會(huì)很好的解決匿名函數(shù)和setTimeout和setInterval的this指向問(wèn)題。不用再去給其變量存儲(chǔ)this。
var obj = {
func:function(){
console.log(this);
},
say:function(){
setTimeout(()=>{
console.log(this)
});
}
}
obj.func();//obj
obj.say();//obj
var a=1;
function test(){
console.log(this.a);
console.log(this);
this.a=2;
return ()=>{console.log(this.a);console.log(this);}
}
var x=new test()();
//undefined
//test {}
//2
//test {a: 2}
注:new test()(),第一個(gè)括號(hào)是返回匿名函數(shù),第二個(gè)括號(hào)是執(zhí)行返回的匿名函數(shù)