原文链接:https://www.jianshu.com/p/c1ee12a328d2
常见的window属性和方法有alter,document,parseInt,setTimeout,setInterval,localtion等等,这些在默认的情况下是省略了window前缀的。(window.alter = alter),所以下文提到箭头函数解决了匿名函数this指向的问题(匿名函数的执行环境具有全局性),包括setTimeout和setInterval中使用this所造成的问题。
以下都是在非严格模式下讨论
1.普通函数中的this
在JavaScript中,this是在函数执行过程中自动生成的一个内部对象,指的就是当前对象。
js的函数可以多层嵌套,如果内层的想要获得外层的this,可以定义一个变量储存起来
var _this=this
在全局函数中,比如匿名函数,this指向的是window。
例子:
var name=" the window";
var obj = {
name:'my obj',
getNameFun:function(){
return function(){
return this.name;
}
}
}
console.log(obj.getNameFun()());// the window
原因是,匿名函数的执行环境是全局的,而且this只在函数内部起作用。此时的this.name在匿名函数中找不到,所以就从全局中找,找到后打印出来。
上面的例子改写一下
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内将this赋给_this,此时的_this指向的是挂载(调用)的对象,即为obj,在匿名函数中调用_this.name会在obj上查找相应的数据,就不会在全局上查找
函数的执行对象放在window
function test(){
console.log(this);
}
test();//window
问题:为啥是window,因为没变量声明?
关于setTimeout和setInterval的this指向问题
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
问题: setTimeout里执行的函数为啥是window,因为setTimeout就是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
执行obj.dbl()时,this.val的this指向obj内的val=2;val在obj内没有定义所以从全局上找val=1,因此运算结果为4 2
func的执行对象是window,我们可以此时全局的val已经等于4了,在经过this.val=2,val=2的运算,打印的结果就是8 8。
问题:为啥执行func,全局的val等于4,不是2?
2.ES6箭头函数this
箭头函数的this定义:箭头函数的this是在定义函数时绑定的,不是在执行过程中绑定的。简单的说,函数在定义时,this就继承了定义函数的对象。
所以,这会很好的解决匿名函数和setTimeout和setInterval的this指向问题。不用再去给其变量存储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()(),第一个括号是返回匿名函数,第二个括号是执行返回的匿名函数