this指向一直被广大面试官所宠爱,也一直困扰着无数的小白们,接下来我们来深入的剖析一下this的指向问题。
言归正传,首先我们先来剖析普通this指向的问题:
首先,我们要了解以下几个概念:
1.预编译过程中this—>window
2.全局作用域里面this—>window
3.一般情况下this—>调用者(谁调用指向谁)
了解了这些概念,接下来我们来看几个例子:
var name = 'zhangsan'
function foo () {
var name = 'lisi'
console.log(this.name)
}
foo(); //zhangsan
在这个简单的例子中很明显,foo()执行,并没有其他对象去调用它,所以这里的this指向window,即this.name ==window.name。
接下来我们来看另一个简单的例子:
var name = 'lisi'
var obj = {
name : 'zhangsan',
say : function(){
console.log(this.name) //zhangsan
self = function(){
console.log(this.name) //lisi
}
self();
},
}
obj.say();
在这个例子中,obj调用say方法,自然而然第一个console.log(this.name)输出的是obj.name即‘zhangsan’,但是self是一个独立的函数,而且后面是该函数的自执行,并没有人调用,所以该函数里的this指向window,所以self里面的this.name==window.name
接下来我们来看一个复杂的例子,将这个例子掌握了,基本的this指向问题也就理解的差不多了
var name = '222'
var a = {
name : '111',
say : function(){
console.log(this.name);
}
}
var fun = a.say;
fun(); //222
a.say(); //111
var b = {
name : '333',
say : function(fun){
fun();
}
}
b.say(a.say); //222
b.say = a.say;
b.say(); //333
我们来逐步分析每一个thi
首先来看第一个fun()执行,我们可以看到有一句代码为var fun = a.say; 我们是不是可以把这句代码理解为下面这样呢?
fun = function(){
consloe.log(this.name)
}
下面的fun自执行,this.name == window.name,是不是这样更好理解一些呢?
接下来我们来看下一个:a.say();
这个就比较简单了,就是简单的谁调用,this指向谁,很明显这里的this.name == a.name
那么难点来了,我们来看b.say(a.say); 可能很多人到这就有点懵了,接下来我们来分析以下这句代码
其实a.say是作为实参来代替b.say里面的形参的,此时b.say可以看成下面这样:
b.say : function(fun){
fun()
}
可能有的人会认为这里不是b调用的say方法吗,this应该指向b呀?我们仔细研究一下会发现,其实是这样的:
b.say : function(fun){
this; //b
fun()
}
这里的this确实是指向了b,但是a.say是作为参数传进b.say然后自执行,所以a.say里面的this与b.say没有任何关系,这里的this.name == window.name
最后一个b.say = a.say就很好理解了,这里你可以理解为b.say利用a.say重写了自身的方法,所以这里的b.say为:
b.say = function(){
console.log(this.name);
}
很明显这里的this指向的就是b,即this.name == b.name
经过上述例子,我们可以发现普通的this指向中,this是在方法调用时确定的。这里和下面要讲的es6中箭头函数的this有所区别。
下一篇我们来讲一下ES6中箭头函数的this指向问题。