【js】关于this的指向情况分析

53 阅读2分钟

1. 普通函数

普通函数的this指向其调用者。

1.1 独立调用

独立调用的普通和匿名函数this指向全局对象(window/globalThis),因为独立调用本质上还是全局对象调用。

独立调用案例1:

let obj = {
  name: "jqm",
  foo: function () {
    function a() {
      console.log("this", this);
    }
    a(); // 独立调用 this指向全局对象
  },
};

obj.foo();复制代码

独立调用案例2:

function foo() {
  console.log(this); //window  obj.foo在bar函数内独立调用
}
function bar(fn) {
  fn();
}
let obj = {
  name: "obj",
  foo: foo,
};
bar(obj.foo);复制代码

1.2 对象调用方法

通过对象调用普通函数,普通函数的this指向调用者

对象调用方法案例1:

let obj = {
  name: "obj",
  foo: function () {
    console.log(this); //this指向obj
  },
};
obj.foo();
复制代码

1.3 显式绑定函数this

js中更改匿名函数this的方法:call、apply、bind。其中bind返回一个新函数,新函数指向绑定的对象,旧函数不会,apply和call直接调用函数,apply和call的区别是,apply第二个参数是数组,call是一个一个的传参。

使用了call、apply或者bind方法调用函数,函数的this指向其第一个参数。

案例:

function a() {
  console.log("this", this);
}

a.call({ name: "jqm" });复制代码

1.4 new绑定

函数通过new 实例化后,函数返回的对象中的this指向实例对象。

2. 箭头函数

箭头函数的this固定指向其父级作用域的上下文(只有两种作用域生效:全局作用域和函数作用域,块级作用域不影响this)。

通俗点讲就是:箭头函数的this指向其上层的第一个普通函数的this。

案例:

var a = 0;
function foo() {
  let test = () => {
    console.log(this);
  };
  return test;
}
let obj = { a: 1, foo };
const fn = obj.foo();

const obj2 = { name: "obj2", fn };

obj2.fn(); // 输出:obj复制代码

注意:如果箭头函数的父级作用域是函数,那么这个箭头函数的this就指向这个函数的this,所以要注意箭头函数的父级函数的调用者。

显式绑定对箭头函数无效:

    var a = 0
    function foo() {
      let test = () => {
        console.log(this)
      }
      return test
    }
    let obj1 = {
      a: 1,
      foo: foo
    }
    let obj2 = {
      a: 2,
      foo: foo
    }
    obj1.foo().call(obj2)
​
     //obj1.foo()返回test   obj1.foo.call(obj2)把test的指向绑定到obj2上,无效,this依然指向obj1复制代码