Skip to content

一文搞懂函数 this 指向

1.案例

箭头函数的应用,让里面的 this 继承外面的函数的,从而得到对象里面的内容!

1.例子一

js
Tabs.prototype.change = function () {
  for (let i = 0; i < this.headerItems.length; i++) {
    this.headerItems[i].addEventListener(
      this.type,
      () => {
        //这里必须用箭头函数,让其继承change函数的this(为什么本身是指向tabs对象的?因为change方法被实例对象tabs调用了,隐式绑定this),否则this指向的就不是tabs对象了,因为普通函数是谁调用就指向谁
        for (let m = 0; m < this.headerItems.length; m++) {
          this.headerItems[m].classList.remove("active");
          this.boxItems[m].classList.remove("active");
        }
        this.headerItems[i].classList.add("active");
        this.boxItems[i].classList.add("active");
      },
      false
    );
  }
};

2.例子二

因为箭头函数(()=>{})没有自己的 this 上下文,它会捕获其所在的词法作用域(也就是定义它的函数或对象的作用域)的 this 值。在这个例子中,箭头函数 next 捕获了 Symbol.iterator 函数的 this,而 Symbol.iterator 函数是在 obj 对象内部定义的,因此 this 指向了 obj 对象。

箭头函数的 this 是词法作用域绑定的,它会捕获定义时(也就是箭头函数被创建时)所处的上下文的 this,而不会受到函数调用方式的影响。

js
var obj = {
  code: 200,
  name: "kerwin",
  list: ["aaaa", "bbbb", "ccc"],
  [Symbol.iterator]: function () {
    let index = 0; //闭包存储
    return {
      next: () => {
        //这里必须用箭头函数,让它的this继承Symbol.iterator函数的this,从而指向obj对象!
        if (index < this.list.length) {
          return {
            value: this.list[index++],
            done: false,
          };
        } else {
          return {
            value: undefined,
            done: true,
          };
        }
      },
    };
  },
};

2.详解

箭头函数与普通函数 this 的区别?箭头函数如何捕获 this?以及对于对象的 this 的理解?

在 JavaScript 中,普通函数的 this 取决于函数被调用时的上下文,可以通过不同的方式调用函数来改变 this 的指向,比如使用 callapply 或者作为对象的方法调用。而箭头函数没有自己的 this 上下文,它会捕获定义时(函数创建时)的上下文的 this

注意:箭头函数捕获的(继承的)一定是它外层距离最近的普通函数的 this,如果没有,那么最终会指向 window/undefined

注意:对象本身是没有 this 的,而是一种用于引用对象的符号,它主要是在一个对象调用一个方法(普通函数)的时候,会把 this 传递给函数(隐式 this 绑定),但是对象本身并不能作为箭头函数的外层 this 供其继承!

在 JavaScript 中,对象是具有属性和方法的实体,而 this 是用来引用当前对象的关键字。在对象内部的方法中,可以使用 this 关键字引用对象本身。

js
//1.fullName是箭头函数的时候,向外继承,外层没有普通函数,this指向window
const person = {
  firstName: "John",
  lastName: "Doe",
  fullName: () => {
    return this.firstName + " " + this.lastName;
  },
};
console.log(person.fullName()); //undefined undefined

//2.fullName是箭头函数的时候,向外继承,继承fun函数的this,fun为箭头函数,继续向外继承,外层没有普通函数,所以this指向window,最终fullName的this也指向了window
const person2 = {
  firstName: "hao",
  lastName: "wenhai",
  fun: () => {
    return {
      firstName: "John",
      lastName: "Doe",
      fullName: () => {
        return this.firstName + " " + this.lastName;
      },
    };
  },
};
console.log(person2.fun().fullName()); //undefined undefined

//3.fullName是箭头函数的时候,向外继承,继承fun函数的this,fun为普通函数,被person3调用,所以this指向person3对象,最终fullName的this也指向person3对象
const person3 = {
  firstName: "hao",
  lastName: "wenhai",
  fun: function () {
    return {
      firstName: "John",
      lastName: "Doe",
      fullName: () => {
        return this.firstName + " " + this.lastName;
      },
    };
  },
};
console.log(person3.fun().fullName()); //hao wenhai

//4.fullName是普通函数的时候,不用向外继承,fun的返回对象调用fullName,所以this指向返回对象!
const person4 = {
  firstName: "hao",
  lastName: "wenhai",
  fun: function () {
    return {
      firstName: "John",
      lastName: "Doe",
      fullName: function () {
        return this.firstName + " " + this.lastName;
      },
    };
  },
};
console.log(person4.fun().fullName()); //John Doe

3.理解

搞懂函数的 this 指向是非常必要的

这对于避免上下文调用的 bug,理解类里面的函数的 this 指向和作用也是很有帮助的!

类里面的 this?

在 JavaScript 中,类中的 this 关键字指向当前实例化的对象,也就是类的实例。类中的 this 可以用来访问和操作实例的属性和方法。

例如,下面是一个简单的类示例:

js
class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  getFullName() {
    //一定用普通函数,否则不能指向我们当前的实例对象!
    return this.firstName + " " + this.lastName;
  }
}

const johnDoe = new Person("John", "Doe");
console.log(johnDoe.getFullName()); // 输出:John Doe

在这个例子中,this.firstNamethis.lastName 用来访问类的实例(即 Person 的实例)的属性。当你创建一个类的实例(const johnDoe = new Person('John', 'Doe')),this 就指向该实例,可以通过 this 访问实例的属性和方法。

需要注意的是,当在类的方法中使用 this 时,确保方法是普通函数而不是箭头函数,以便正确绑定 this。箭头函数没有自己的 this 上下文,会捕获其外层最近一层非箭头函数的 this。在类中,通常我们会使用普通函数来确保正确的 this 绑定到实例。