# 关于this

注意

this关键字是JavaScript 中最复杂的机制之一。是一个很特别的关键字,被自动定义在所有的函数作用域中。

function identify () {
  return this.name.toUpperCase()
}

function speak () {
  var greeting = 'Hello, 我是' + identify.call(this)
  console.log(greeting)
}

var me = {
  name: 'Kyle'
}

var you = {
  name: 'Reader'
}

identify.call(me) // KYLE
speak.call(you) // Hello, 我是 READER

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

this在任何情况下都不指向函数的词法作用域。在JavaScript内部,作用域确实和对象类似,可见的标识符都是他的属性,但是作用域“对象”无法通过JavaScript代码访问,他存在于JavaScript 引擎内部。

# this 是什么

this 是在运行时进行绑定的,并不是编写时绑定,他的上下文取决于函数调用时的各种条件。this 的绑定和函数声明的位置没有关系,只取决于函数的调用方式。它指向什么完全取决于函数在哪里被调用

当一个函数被调用时,会创建一个活动记录(有时候也称为执行上下文)这个记录包含函数在哪里被调用(调用栈)、函数的调用方法、传入的参数等信息。this就是记录的其中一个属性,会在函数执行的过程中用到。

# this 的绑定规则

  • 默认绑定(独立函数的调用)
function foo() {
  console.log(this.a)
}

var a = 2

foo() // 2

1
2
3
4
5
6
7
8

严格模式下,全局对象无法使用默认绑定,this 会绑定undefined

  • 隐式绑定

调用位置是否有上下文对象,或者说是否被某个对象拥有或者包含

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

var obj = {
  a: 2,
  foo: foo
}

obj.foo() // 2
1
2
3
4
5
6
7
8
9
10

foo 这个函数严格来说不属于obj对象,调用位置会使用 obj 上下文来引用函数,可以说函数被调用时 obj 对象拥有或者包含它。

对象属性引用链中只有最顶层或者说最后一层会影响调用位置。

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

var obj2 = {
  a: 42,
  foo: foo
}

var obj1 = {
  a: 2,
  obj2: obj2
}

obj1.obj2.foo() // 42
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

隐式丢失

一个最常见的this绑定问题就是被隐式绑定的函数会丢失绑定对象,也就是说它会应用默认绑定,从而把this绑定到全局对象或者undefined上




1
2
3