解决使用 ES9 箭头函数时遇到的 this 问题

解决 ES9 箭头函数 this 问题

在前端开发中,我们经常使用箭头函数来简化代码,而 ES9 中的箭头函数也为我们带来了更多的便利。然而,与普通函数不同的是,箭头函数中的 this 绑定规则很容易出现问题。本文将介绍在使用 ES9 箭头函数过程中遇到的 this 问题,以及如何解决这些问题。

函数的 this 绑定规则

在 JavaScript 中,函数的 this 绑定规则是非常灵活的。简单来说,this 的取值是在函数被调用时动态绑定的,而不是在函数定义的时候绑定的。根据函数的调用方式不同,this 的取值也会不同。

通常情况下,函数的 this 取值如下:

  • 方法:被对象调用的函数中的 this 指向该对象。
const obj = {
  name: 'Jack',
  sayName() {
    console.log(this.name);
  }
};
obj.sayName(); // Jack
  • 普通函数:在全局作用域中调用的函数中的 this 指向全局对象(浏览器中为 window,在 Node.js 中为 global)。
function sayName() {
  console.log(this.name);
}
sayName(); // undefined(浏览器中)
  • 构造函数:使用 new 关键字调用的函数中的 this 指向新创建的实例对象。
function Person(name) {
  this.name = name;
}
const person = new Person('Jack');
console.log(person.name); // Jack
  • apply、call、bind 方法:调用这些方法来显式地指定函数中的 this。
function sayName() {
  console.log(this.name);
}
const obj = {
  name: 'Jack'
};
sayName.call(obj); // Jack

ES9 箭头函数中的 this 绑定

在 ES6 中,箭头函数继承了它所在上下文中的 this 绑定。简单来说,箭头函数中的 this 始终指向它所在的上下文中的 this,而不是在函数定义时绑定的。

const obj = {
  name: 'Jack',
  sayName() {
    const inner = () => {
      console.log(this.name);
    };
    inner();
  }
};
obj.sayName(); // Jack

上面的例子中,箭头函数 inner 定义在对象 obj 的方法 sayName 中,并且内部引用了 this。由于箭头函数的 this 继承了它所在上下文的 this,inner 中的 this 指向了 obj 中的 this,因此输出为 Jack。

然而,在实际开发中,我们会发现箭头函数的 this 绑定会出现问题,比如以下情况:

  • 在全局作用域中使用箭头函数。
const obj = {
  name: 'Jack',
  sayName() {
    const inner = () => {
      console.log(this.name);
    };
    inner();
  }
};
const inner = () => {
  console.log(this.name);
};
inner(); // undefined(浏览器中)
  • 在对象的原型方法中使用箭头函数。
class Person {
  constructor(name) {
    this.name = name;
  }
  sayName() {
    console.log(this.name);
  }
}
Person.prototype.sayNameArrow = () => {
  console.log(this.name);
};
const person = new Person('Jack');
person.sayName(); // Jack
person.sayNameArrow(); // undefined(浏览器中)
  • 使用箭头函数定义对象的方法。
const obj = {
  name: 'Jack',
  sayName: () => {
    console.log(this.name);
  }
};
obj.sayName(); // undefined(浏览器中)

在上述情况中,箭头函数中的 this 绑定失效了,输出结果为 undefined。这是因为箭头函数的 this 继承了它所在上下文的 this,而这些上下文并不符合函数的 this 绑定规则。下面我们将介绍如何解决这些问题。

解决 this 绑定问题

1. 显式绑定 this

如果箭头函数所在的上下文并不符合函数的 this 绑定规则,可以使用 apply、call 或者 bind 显式地将 this 绑定到正确的值。

const obj = {
  name: 'Jack',
  sayName: () => {
    console.log(this.name);
  }
};
obj.sayName.call(obj); // Jack

2. 使用对象方法

可以使用对象方法来代替箭头函数,这样就可以使用对象上下文中的 this。

const obj = {
  name: 'Jack',
  sayName() {
    console.log(this.name);
  }
};
obj.sayName(); // Jack

3. 使用闭包保存正确的 this 值

可以使用闭包保存正确的 this 值,然后在箭头函数内部使用闭包中的 this 值。

const obj = {
  name: 'Jack',
  sayName() {
    const self = this;
    const inner = () => {
      console.log(self.name);
    };
    inner();
  }
};
obj.sayName(); // Jack

4. 使用 ES8 中的 async/await

在使用 async/await 的过程中,可以使用 async 函数中的 this 来代替箭头函数中的 this。

const obj = {
  name: 'Jack',
  async sayName() {
    console.log(this.name);
  }
};
(obj.sayName)(); // Jack

5. 让箭头函数嵌套在普通函数中

如果箭头函数需要使用普通函数中的 this,可以让箭头函数嵌套在普通函数中,这样箭头函数就可以继承普通函数中的 this 绑定规则。

class Person {
  constructor(name) {
    this.name = name;
  }
  sayName() {
    console.log(this.name);
  }
  sayNameArrow() {
    const inner = () => {
      console.log(this.name);
    };
    inner();
  }
}
const person = new Person('Jack');
person.sayName(); // Jack
person.sayNameArrow(); // Jack

总结

ES9 中的箭头函数为我们带来了更多便利,同时也带来了 this 绑定问题。在实际开发中,我们可以使用以上方法来解决箭头函数中的 this 绑定问题,从而提高开发效率和代码质量。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6593d3b5eb4cecbf2d873788


纠错反馈