写在前面

理解 this,记住以下两点:

  • this 永远指向一个对象
  • this 的指向完全取决于调用的位置

更深层次的原因

JS 中的数据类型可以分为:基本数据类型和引用类型。其中,数组、函数、对象都是引用类型,参数传递时也是引用传递(可单独讲一下)。而函数既可以当成值传递,也可以当成对象和构造函数,所以函数运行时需要确定其当前的运行环境,因此,this 只有在函数运行时才可以最终确定运行环境(this 对于运行环境的动态切换规则)。

聊一聊 this 的几个常用使用场景

  • 事件绑定
  • 构造函数
  • 定时器
  • call()
  • apply()

事件绑定

三种方式:

  • 行内绑定
  • 动态绑定
  • 事件监听

定时器

var obj={
    fun:function(){
        this;
    }
}
setInterval(obj.fun,100);	// this 指向 window
setInterval("obj.fun()",100);	// this 指向 obj

setInterval(obj.fun,100)其实是将 fun 这个函数的地址作为参数传递给了 setInterval方法(这个时候跟 obj 对象已经半毛钱关系都没有了),那么 100 毫秒后,函数的运行就是在 window 对象下了;

setInterval("obj.fun()",100)的第一个参数其实是一段可执行代码,当 js 开始执行这段代码时,是先找到 obj 下的 fun 函数并调用执行,所以函数的运行环境仍然在 obj 对象内,所以 this 就指向 obj 对象了。

call() && apply()

  • call()
func.call(obj,arg1,arg2,...argN)
// obj 是 this 要指向的对象
// arg1... 是参数列表
  • apply()
func.apply(obj,[arg1,arg2,...argN])
// obj 是 this 要指向的对象
// [arg1...] 是参数列表,要求是数组

Call 和 Apply 作用一致,只是函数实参的传递方式不一样,二者都用来强制指定函数调用时 this 的指向。

关于 闭包的 this 指向问题,后面会单独拉一篇文章出来讲。

参考