返回

this 指向问题(call,apply,bind)剖析

前端

在 JavaScript 中,this 是一个特殊的,它代表当前执行代码的对象。在不同的上下文中,this 可以有不同的值,这被称为“this指向问题”。在 ES5 中,this 总是指向最后调用它的对象。

改变 this 指向

在 ES5 中,我们可以使用以下几种方法来改变 this 指向:

  • 使用 ES6 箭头函数
  • 在函数内部使用 _this = this;
  • 使用 apply()call()bind()
  • 使用 new 实例化一个对象

使用 ES6 箭头函数

ES6 箭头函数没有自己的 this 值,它总是继承其外层函数的 this 值。因此,我们可以使用箭头函数来改变 this 指向。例如:

const person = {
  name: 'John',
  sayHello() {
    console.log(`Hello, my name is ${this.name}`);
  }
};

const sayHello = () => {
  console.log(`Hello, my name is ${this.name}`);
};

person.sayHello(); // Hello, my name is John
sayHello(); // 报错:this.name is undefined

在上面的例子中,person.sayHello() 方法中的 this 指向 person 对象,而 sayHello() 函数中的 this 指向 undefined。这是因为 sayHello() 函数是一个箭头函数,它没有自己的 this 值,它继承了外层函数 (person.sayHello()) 的 this 值。

在函数内部使用 _this = this;

我们可以在函数内部使用 _this = this; 来保存 this 的值,然后在函数内部使用 _this 来代替 this。例如:

const person = {
  name: 'John',
  sayHello() {
    const _this = this;
    setTimeout(function() {
      console.log(`Hello, my name is ${_this.name}`);
    }, 1000);
  }
};

person.sayHello(); // Hello, my name is John

在上面的例子中,我们使用 _this = this; 来保存 this 的值,然后在 setTimeout() 函数内部使用 _this 来代替 this。这样,即使在 setTimeout() 函数内部,this 仍然指向 person 对象。

使用 apply(), call()bind()

apply(), call()bind() 是三个内置函数,它们可以改变 this 指向。

  • apply() 函数接受两个参数:第一个参数是 this 的值,第二个参数是一个数组,包含要传递给函数的参数。
  • call() 函数与 apply() 函数类似,但它接受一个参数,而不是一个数组。
  • bind() 函数返回一个新的函数,这个函数的 this 值被固定为指定的值。

例如:

const person = {
  name: 'John',
  sayHello() {
    console.log(`Hello, my name is ${this.name}`);
  }
};

const sayHello = function() {
  console.log(`Hello, my name is ${this.name}`);
};

sayHello.apply(person); // Hello, my name is John
sayHello.call(person); // Hello, my name is John
const boundSayHello = sayHello.bind(person);
boundSayHello(); // Hello, my name is John

在上面的例子中,我们使用 apply()call()bind() 函数来改变 this 指向。

使用 new 实例化一个对象

当我们使用 new 关键字实例化一个对象时,this 指向这个新对象。例如:

class Person {
  constructor(name) {
    this.name = name;
  }

  sayHello() {
    console.log(`Hello, my name is ${this.name}`);
  }
}

const person = new Person('John');
person.sayHello(); // Hello, my name is John

在上面的例子中,我们使用 new 关键字实例化了一个 Person 对象,然后调用 sayHello() 方法。this 指向 person 对象,因此 this.name 等于 'John'

总结

在本文中,我们详细分析了this指向问题,并介绍了ES6箭头函数、apply、call、bind和new实例化对象等改变this指向的方法。希望通过本文,你能对this指向问题有更深入的理解。