# 关于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
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
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
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
隐式丢失
一个最常见的this绑定问题就是被隐式绑定的函数会丢失绑定对象,也就是说它会应用默认绑定,从而把this绑定到全局对象或者undefined上
1
2
3
2
3