你需要知道JavaScript:this指向问题

demongao
2667
2020-11-03

this 是在运行时绑定的,并不是在编写时绑定的.它的上下文取决于函数调用时的各种条件.

首先明白

  1. this 既不指向函数自身,也不指向函数的词法作用域

this绑定规则

  1. 默认绑定
    独立函数调用
function foo(){
      console.log(this.a);
}
var a = 2;
//函数调用时应用了this的默认绑定,因此this指向全局对象.
foo(); //2 
  1. 隐式绑定
    调用的位置是否有上下文对象,或者说被某个对象拥有或包含,不过这种说法可能造成一些误导.
function foo(){
      consle.log(this.a);
}
var obj = {
      a:2,
      foo:foo
}
obj.foo(); //2

隐式丢失: 函数别名和参数传递 ,最经常遇见的setTimeout(fn,delay)函数,会发生隐式丢失,this指向window

//函数别名
function foo(){
      console.log(this.a);
}
var obj = {
      a:2,
      foo:foo
}
var bar = obj.foo;
var a = "oops,global";
bar();//"oops,global"
//参数传递
function foo(){
      console.log(this.a);
}
var obj = {
      a:2,
      foo:foo
}
var bar = obj.foo;
var a = "oops,global";
function doFoo(fn){
      fn();
}
doFoo(obj.foo);//"oops,global"
  1. 显示绑定

  2. 硬绑定
    使用call(...) apply(...)

  3. API调用的"上下文"
    如[1,2,3].forEach(foo,obj) ,当执行回调函数时用作this的值(参考对象)。

  4. new绑定

  5. 创建(或者说构造)一个全新的对象

  6. 这个新对象都会被执行[[Prototype]]

  7. 这个新对象会绑定到函数调用的this

  8. 如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回一个新对象.

  9. =>(箭头函数)
    箭头函数看上去是匿名函数的一种简写,但实际上,箭头函数和匿名函数有个明显的区别:箭头函数内部的this是词法作用域,由上下文确定。即箭头函数没有自己的this,其中的this会自动从上一级继承

函数参数会使其丢失this,从而指向window, 使用箭头函数可以修改this指向,this是词法作用域由上下文确定

let a = {
    x: 1,
    y: function() {
        setTimeout(() => {
            console.log('this', this)
        }, 1000)
    }
}
a.y() // this a
let a = {
    x: 1,
    y:() => { // y:() => {}, this继承上一级, this = window
        setTimeout(() => {
            console.log('this', this)
        }, 1000)
    }
}
a.y() // this window