前言
this
是 JavaScript 中的一个关键字,它指向一个对象。在不同场合,this
有不同含义,在 严格模式 与 非严格模式 之间它也有一些区别。
那么如何判断 this 关键字的指向呢?首先需要记住的一点是,this 所指的对象取决于它使用的时候所处的环境,而不是它定义的时候所处的环境(箭头函数除外)。下面分几种情况来分别讨论。
全局上下文中的 this 值
在全局上下文环境中,this 总是指代 全局对象 ,无论是否在严格模式下。
|
|
浏览器中的全局对象通常是 window 对象。
函数上下文中的 this 值
在函数内部,this 值取决于函数的调用方式。
直接调用函数
如果函数是被直接调用的,那么函数内部的 this 值在非严格模式下指向 全局对象 ,在严格模式下 this 将保持它进入执行环境时的值,如果 this 未被执行的上下文环境定义,那么它会是 undefined
。
|
|
对象方法中的 this
当以对象里的方法的方式调用函数时,它们的 this 指向调用该函数的对象。
|
|
注意,在何处或者如何定义函数完全不影响 this 的行为,this 值是在函数调用时而不是定义时绑定。看下面这个例子:
|
|
我们首先定义一个函数,然后再将其添加到o.f。这样做 this 值也指向了 o 对象。
类似的,this 的绑定只受最靠近的成员引用的影响。在下面的这个例子中,我们把一个方法 g 当作对象 o.b 的函数调用。在这次执行期间,函数中的 this 将指向 o.b。
|
|
原型链中的 this
同样的,定义在对象原型链中的方法的 this 值也是指向直接调用这个方法的对象,就好像是这个方法就存在于这个对象上一样。
|
|
这个例子中,对象 p 没有属于自己的 f 属性,它的 f 属性在它的原型对象上。但是在调用 p.f()
时,f() 的 this 值仍然指向了 p 对象。
getter 与 setter 中的 this
当一个函数作为 getter 或 setter 调用时,再次,它们都会绑定 this 到设置属性或得到属性的那个对象。
|
|
构造函数中的 this
当一个函数被作为一个构造函数来使用时,它的 this 会与被它创建的新实例对象绑定。
|
|
闭包中的 this
在闭包内层函数里的 this,由于闭包的函数没有直接调用对象,它会在非严格模式下指向全局对象 global/window,严格模式下为 undefined。
|
|
事件处理函数中的 this
内联事件处理函数中的 this
当代码被内联处理函数调用时,它的 this 指向监听器所在的 DOM 元素。
|
|
上面的 alert 会显示 button。但注意只有外层代码中的 this 是这样设置的。看下面的例子:
|
|
在这种情况下,没有设置内部函数的 this,所以它指向 global/window 对象。
DOM 事件处理函数中的 this
当一个函数被用作事件处理函数时,它的 this 指向触发该事件的元素。
|
|
显式绑定 this 值
以上所讲的都是 this 值的默认绑定与隐式绑定,但 JavaScript 提供的绝大多数函数以及我们自
己创建的所有函数都可以使用 call()
, apply()
以及 ES5 引入的 bind()
方法来显式绑定函数的 this 指向。
call() 和 apply() 方法
当一个函数的函数体中使用了 this 关键字时,通过所有函数都从 Function 对象的原型中继承的 call() 方法和 apply() 方法调用时,它的值可以绑定到一个指定的对象上。
|
|
bind() 方法
ECMAScript 5 引入了 Function.prototype.bind。调用 f.bind(someObject)
会创建一个与 f 具有相同函数体和作用域的函数,但是在这个新函数中,this 将永久地被绑定到了 bind 的第一个参数,无论这个函数是如何被调用的。
|
|
ES6 箭头函数的 this 值
ECMAScript 6 引入了 箭头函数 (=>
)的概念。
箭头函数内部没有自己的 this 值,它的 this 是来自它的包含环境上下文的。
|
|
由于箭头函数的 this 已经在词法层面完成了绑定,所以通过 call() 或 apply() 方法调用一个函数时,只是传入了参数而已,对 this 并没有什么影响:
|
|
总结
简单做一下总结,在判断一个 this 值的指向时,有以下几个原则:
- 原则一: this 指向的是直接调用函数的那个对象,没有的话就指向全局对象 global/window(非严格模式)。
- 原则二: this 指向的对象就是它使用的时候(不是定义的时候)所处的环境的上下文。
- 原则三: 当 new 关键字出现时,this 指代 new 出来的那个对象。