this的指向问题是JS中比较经典的问题,也很重要。在看了《你不知道的JavaScript》之后,想来总结一下。
关于this先要知道几个点
- this指向是在函数调用时才绑定
- 它的上下文取决于函数调用时的各种条件
- this的指向取决于函数的调用方式
通过函数的调用位置找到对应的绑定规则,确定this的指向(箭头函数单独说)
四条绑定规则
- 默认绑定
主要像一些独立函数的调用。非严格模式指向全局对象,严格模式指向undefined - 隐式绑定
当函数引用有上下文对象时,隐式绑定规则会把函数调用中的this绑定到这个上下文对象。
这样讲有点难懂,举个例子:
function foo(){
console.log(this.a);
}
var obj = {
a : 2,
foo : foo
};
obj.foo();//2
foo函数调用时,它的前面加上了对obj的引用,所以foo函数里面的this就被绑定到obj对象上。
这里还有个最常见的隐式绑定问题就是隐式丢失,看下面的代码:
function foo() {
console.log(this.a);
}
var obj = {
a : 2,
foo : foo
};
var bar = obj.foo;
var a = "global";//a是全局对象的属性
bar();//"global"
我开始一直不明白,按照之前的讲解,我认为这里打印的应该是2,但是却打印的是全局环境下的a。想了很久,知道又看到那句话才恍然大悟。“this指向是在函数调用时才绑定”。在这里bar是对函数foo的引用。所以执行这段代码的时候 var bar = obj.foo; 并没有绑定this,当执行bar()时,调用了bar函数,又因为调用位置是在全局环境下,所以this指向window。全局环境下的a的值是"global"
- 显示绑定
简单的说就是由call,apply或者bind调用 - new绑定
我个人理解就是构造函数中的this,绑定到新创建的对象
四条规则其实还有一个优先级顺序
new绑定 > 显示绑定 > 隐式绑定 > 默认绑定
箭头函数的this
箭头函数不适用上面的四条规则,箭头函数本身是没有this的,它会继承外层函数调用时的this绑定。
总结一下判断this的绑定对象方法
1.找到函数的直接调用位置
2.根据优先级去应用四条规则
注:箭头函数除外,另外还需要注意一些例外情况比如间接引用等