this 的绑定
Mark Peng 12/21/2022 JavaScriptthis
# 绑定规则
# 默认绑定
var a = 1
function foo () {
console.log(this.a)
}
foo() // 1
1
2
3
4
5
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
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
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
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
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 全面解析 记录。