# this
过 this 是在运行时进行绑定的,并不是在编写时绑定,它的上下文取决于函数调 用时的各种条件。this 的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。
# 错误理解
指向自身
第二种常见的误解是,this 指向函数的作用域
# this的几种情况
this 实际上是在函数被调用时发生的绑定,它指向什么完全取决于函数在哪里被调用。
# 默认绑定
首先要介绍的是最常用的函数调用类型:独立函数调用。可以把这条规则看作是无法应用其他规则时的默认规则。
function foo() {
console.log( this.a );
}
var a = 2;
foo(); // 2
1
2
3
4
5
6
2
3
4
5
6
在本例中,函数调用时应用了 this 的默认绑定,因此 this 指向全局对象,如果使用严格模式(strict mode),那么全局对象将无法使用默认绑定,因此 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
2
3
4
5
6
7
8
# 隐式丢失
一个最常见的 this 绑定问题就是被隐式绑定的函数会丢失绑定对象,也就是说它会应用默认绑定,从而把 this 绑定到全局对象或者 undefined 上,
function foo() {
console.log( this.a );
}
var obj = {
a: 2,
foo: foo
};
var bar = obj.foo; // 函数别名!
var a = "oops, global"; // a 是全局对象的属性
bar(); // "oops, global"
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# 显式绑定
可以使用函数的 call(..) 和apply(..) 方法
# new绑定
function foo(a) {
this.a = a;
}
var bar = new foo(2);
console.log( bar.a ); // 2
1
2
3
4
5
2
3
4
5
# 判断this
- 函数是否在 new 中调用(new 绑定)?如果是的话 this 绑定的是新创建的对象。
var bar = new foo() - 函数是否通过 call、apply(显式绑定)或者硬绑定调用?如果是的话,this 绑定的是指定的对象。
var bar = foo.call(obj2) - 函数是否在某个上下文对象中调用(隐式绑定)?如果是的话,this 绑定的是那个上下文对象。
var bar = obj1.foo() - 如果都不是的话,使用默认绑定。如果在严格模式下,就绑定到 undefined,否则绑定到全局对象。
var bar = foo()
# es6例外:箭头函数
箭头函数不使用 this 的四种标准规则,而是根据外层(函数或者全局)作用域来决定 this。
← (原型)继承-原型链 手写代码 →