对于刚开始学习javascript的朋友来说,this指向可能算是一个比较头疼的事了,我们总是在写代码时,搞不清在各个位置的this究竟指的谁,一会对象,一会方法,一会window的,甚是烦人。反正我刚学的时候,是碰过很多壁的。现在算是对this有了一些新的认识吧,写在这里分享一下,如果能有谁在百度的时候进来看到,也算是值了。

首先,网上比较流行的一个说法是说,this指向的是自身。这个说法完全错误,如果你也前是这么认为的,希望你从此刻开始,马上从脑子里根除你的这一认识,不管你是从哪学来的这一观点。为什么我这么肯定的说呢,我们先来看下面这个例子:

这个结果是不是已经很明确的说明了问题,如果this指向自身的话,那么打印出来的应该是5才对。那结果为什么是undefined呢,因为this指向了window对象(不信你可以在console.log(this.a)的前面写上一句console.log(this),看控制台打印的是不是window),但是我们这里斌没有全局的a,故结果为undefined。

第二种说法,this指向函数的作用域。这种说法和第一种比起来,要准确一些,但也不对,为什么呢,就上面这个例子而言,它是对的,因为函数lgx()的作用域是全局的,而this又指向了window。但为什么也说它不对呢,我们再来看下面这个例子:

这就奇怪了,函数的作用域并没有改变啊,可这次为什么又能好好的打出5来了呢。知道call的朋友也许会说了,那是因为你用了call函数把this绑定到了lgx上,如果你能这样想,那你就对了。

是的,通过上面的两个例子我们已经可以很明确的说,上面两种说法均不正确。那this的指向到底是怎么回事呢。我们只能这样说了:this的指向取决于函数的调用方式和看它是否存在绑定。就拿我们这里的代码来说,第一次和第二次,一个没有绑定,一个有绑定,结果就不一样,那指向肯定就跟绑定有关了。可为什么说跟调用方式有关呢,我们再看下面的例子:

怎么样?同一个对象的同一个方法,调用方式不同,this的指向是不是也变了。

下面我们先说一下this的绑定问题,在js中,this有多种绑定,最常见的分别是默认绑定, 隐式绑定,显示绑定,new绑定。

所谓默认绑定,就是当一个独立函数在没有任何修饰的情况下调用时,this默认指向window,就像这样:

独立函数的意思是这个函数不属于任何对象,没有任何修饰,则是指函数的执行作用域是属于window,没有被改变。

隐式绑定,则是在默认绑定的情况下,如果我们改变了函数执行的上下文,则this会被绑定到指定的上下文对象上。我们看下面这个例子:

这里,我们给obj这个对象定义一个属性b,让其引用lgx这个方法,然后执行obj.b,从结果我们可以看出,lgx里的this指向了obj,原因就是因为当我们通过obj.b调用时,lgx函数的上下文被改变成了obj,this自然就指向obj这个对象了。

显示绑定,就是我们眼睛能看得见的绑定,比如Js中常用的call和apply这两个方法,我们都知道他们会改变this的指向,并且是call谁this就指向谁。例子如下:

其实,通过call和apply进行的绑定我们也可以叫做硬绑定,因为通过call和apply绑定过后的this,当我们再次使用call和apply进行绑定时,this的指向是不会再改变的,正所谓硬绑定,就是绑定死了的意思。且看下面:

由于硬绑定是一种非常常用的模式,所以在ES5中已经提供了内置的使用方法,即bind,使用如下:

bind会返回一个硬编码的新函数,它会把this的上下文设置为绑定对象并调用原始函数。

最后一个是new绑定,js中,当使用new来调用函数,或者发生构造函数调用时,会自动执行下面的这些操作:

1、创建或构造一个全新的对象;

2、这个新对象会被执行【原型】链接;

3、函数调用的this会绑定到该对象上;

4、如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新对象。

其中,我们要关心的是1,3,4这三步,对于2,是跟原型有关的东西,我这里不做过多说明。我们来看下面的代码:

由于用到了new来构造一个新的对象,所以lgx中的this也就指向了这个新对象。

当然,除了这几种绑定,也有个别另外的情况,我就不再一一举例说明了,正所谓js是世界上最灵活的语言,这绝对不是吹的,也许偶尔你会看到一些千奇百怪的写法,可能在之前连见都没见过,但它就是能正确运行。这是高人的另一片天地,至于你能不能到达,就全看你的造化了。本人太懒,这么一小篇文章分了两个星期才写完,如果阅读的朋友发现有什么不对的地方,欢迎指正。