this是和执行上下文绑定的,也就是说每个执行上下文中都有一个 this,执行上下文分为3种:

①全局执行上下文

②函数执行上下文

③eval执行上下文

所以对应的this也只有这三种,全局执行上下文中的 this、函数中的 thiseval 中的 this

全局执行上下文中的this

局执行上下文中的 this 是指向 window 对象的

函数执行上下文中的this

现在你已经知道全局对象中的 this 是指向 window 对象了,那么接下来,我们就来重点分析函数执行上下文中的 this。还是先看下面这段代码:

function foo(){
  console.log(this)
}
foo()

我们在 foo 函数内部打印出来 this 值,执行这段代码,打印出来的也是 window 对象(非严格模式),这说明在默认情况下调用一个函数,其执行上下文中的 this 也是指向 window 对象的。估计你会好奇,那能不能设置执行上下文中的 this 来指向其他对象呢?答案是肯定的。通常情况下,有下面三种方式来设置函数执行上下文中的 this 值。

通过函数的call方法设置

你可以通过函数的 call 方法来设置函数执行上下文的 this 指向,比如下面这段代码,我们就并没有直接调用 foo 函数,而是调用了 foocall 方法,并将 bar 对象作为 call 方法的参数

let bar = {
  myName : “hk”,
  test1 : 1
}
function foo(){
  this.myName = “lcf”
}
foo.call(bar)
console.log(bar)
console.log(myName) // 报错 未定义 myName

执行这段代码,然后观察输出结果,你就能发现 foo 函数内部的 this 已经指向了 bar 对象,因为通过打印 bar 对象,可以看出 barmyName 属性已经由“极客邦”变为“极客时间”了,同时在全局执行上下文中打印 myName,JavaScript 引擎提示该变量未定义。

其实除了 call 方法,你还可以使用 bindapply 方法来设置函数执行上下文中的 this,它们在使用上还是有一些区别的,如果感兴趣你可以自行搜索和学习它们的使用方法,这里我就不再赘述了。

通过对象调用方法设置

要改变函数执行上下文中的 this 指向,除了通过函数的 call 方法来实现外,还可以通过对象调用的方式,比如下面这段代码:

var myObj = {
  name : "hk", 
  showThis: function(){
    console.log(this)
  }
}
myObj.showThis()