由于this的运行期绑定的特性,它可以是全局对象,当前对象或者任意对象,这完全取决于函数的调用方式。
函数是否被new操作符调用
Javascript中没有类的概念,相应的,它的构造函数的概念也十分的特别。如果没有用new操作符调用,就和普通函数一样,如果有了new,就变成了一个构造函数。作为一个约定俗成的写法,构造函数以大写字母开头。
1 | function Point(x, y){ |
如果是一个构造函数,this绑定到新构造出来的函数中。也就是说上面这段代码会生成一个对象,将this绑定到这个对象上,函数执行结束之后返回这个对象。
函数是否通过apply和call调用
在Javascript中函数也是对象,是一种特殊的对象。那么函数也有属性也有方法,最著名的属性是prototype
,最著名的方法是apply
和call
。apply和call的区别是如果知道传入函数的参数就使用call,如果不确定参数,使用的是arguments数组传参,那么就用apply。
1 | function Point(x, y){ |
首先利用构造函数生成一个对象p1,该对象具有moveTo方法。利用对象字面量的方法生成另外一个对象p2。调用p1.moveTo的apply(通过数组传递参数)方法,将运行时这个函数的this绑定到apply中的第一个参数也就是p2对象上。
总结一下,利用apply和call方法,就是将调用这个方法的函数运行时的this绑定到第一个参数。在例子中,就是将this.moveTo方法的this绑定到p2对象中。
函数是否有对象上下文
通俗的说就是这个函数是不是对象调用的,比方说上面那个例子中的p1.moveTo(1,1),这个moveTo方法就是p1对象调用的,等价于p1.moveTo(p1,[1,1])。 如果函数调用有对象上下文,this绑定到这个对象。
1 | var point = { |
上面这个例子就是将函数里面的this绑定到调用的对象上。
如果上面这些都没有
如果函数执行的时候没有new,也不是通过apply和call调用的,前面也没有对象,那么this就是绑定到window当中。据说这个设计是毫无用处的,不管在什么情况下,我们都不需要将this绑定到window,但是它就是这么设计的,记住它吧。
1 | var point = { |
总结
this的绑定就上面这四种情况,分析起来还是不难的吧?在新的ES6标准中fat arrow也会涉及到this的绑定。