this 的绑定

12/21/2022 JavaScriptthis

# 绑定规则

# 默认绑定

var a = 1
function foo () {
  console.log(this.a)
}
foo() // 1
1
2
3
4
5

函数在调用时应用了 this 的默认绑定,因此 this 指向全局对象,this.a 被解析成全局变量 a。

# 隐式绑定

function foo () {
  console.log(this.a)
}
var obj = {
  a: 2,
  foo: foo
}
obj.foo() // 2
1
2
3
4
5
6
7
8

使用 obj 来引用函数,隐式绑定会把函数的 this 绑定到这个上下文对象,因此调用时 this 被绑定到 obj,this.a 和 obj.a 是一样的。

隐式丢失

function foo () {
  console.log(this.a)
}
var obj = {
  a: 1,
  foo: foo
}
var a = 2
var bar = obj.foo
bar() // 2
1
2
3
4
5
6
7
8
9
10

实际上,bar 只是对 foo 函数的引用,此时的 bar() 是一个不带任何修饰的函数调用,因此应用了默认绑定。

# 显示绑定

关于 this 的显示绑定,参照 apply、call、bind (opens new window) 这一篇。

# new 绑定

function foo (a) {
  console.log(this.a)
}
var bar = new foo(2)
console.log(bar.a) // 2
1
2
3
4
5

使用 new 来调用 foo() 时,会创建一个新对象并把它绑定到 foo() 调用的 this 上。

# 绑定例外

ES6 中出现了一种无法适用这些绑定规则的特殊函数类型:箭头函数,它是根据外层函数、全局作用域来决定 this 。

function foo () {
  return () => {
    console.log(this.a)
  }
}
var obj1 = {
  a: 1
}
var obj2 = {
  a: 2
}
var bar = foo.call(obj1)
bar.call(obj2) // 1
1
2
3
4
5
6
7
8
9
10
11
12
13

foo() 内部创建的箭头函数会捕获调用时 foo() 的 this。由于 foo() 的 this 绑定在 obj1,bar(引用箭头函数)的 this 也会绑定到 obj1,箭头函数的 this 无法改变。

# 总结

this 绑定四条规则:

  • 由 new 调用:绑定到新创建的对象
  • 由 call、apply、bind 调用:绑定到指定对象
  • 由上下文对象调用:绑定到那个上下文对象
  • 默认:严格模式下绑定到 undefined ,否则绑定到全局对象

this 绑定例外:

  • ES6 中的箭头函数不适用以上四条规则,箭头函数会继承外层函数调用的 this 绑定。

参考

学习《你不知道的 JavaScript》上卷 this 全面解析 记录。

Last Updated: 12/22/2022, 3:42:37 PM