返回

在 JavaScript 中,this 指向有何奥妙?这些栗子助你深入理解

前端

前言

在 JavaScript 中,this 指向是一个非常重要的概念,但也是很多开发者头疼的问题。this 指向会随着函数的调用方式和执行上下文而改变,这使得理解和使用 this 指向变得困难。

本文将通过七个栗子,深入浅出地讲解 this 指向的奥妙,帮助你彻底理解 this 指向的规则,让你在开发中不再为 this 指向而烦恼。

栗子 1:函数中的 this 指向

function Person() {
  this.name = "John";
}

const person = new Person();
console.log(person.name); // "John"

在这个栗子中,我们在函数 Person 中使用 this 来访问和修改对象 person 的属性 name。当我们使用 new 关键字调用函数 Person 时,会创建一个新的对象 person,并将其作为函数 Person 的 this 指向。因此,在函数 Person 中,this 指向对象 person,我们可以通过 this.name 来访问和修改对象 person 的属性 name。

栗子 2:方法中的 this 指向

const person = {
  name: "John",
  getName: function() {
    return this.name;
  }
};

console.log(person.getName()); // "John"

在这个栗子中,我们在对象 person 中定义了一个方法 getName,并在方法 getName 中使用 this 关键字来访问和修改对象 person 的属性 name。当我们调用方法 person.getName() 时,方法 getName 的 this 指向对象 person,因此我们可以通过 this.name 来访问和修改对象 person 的属性 name。

栗子 3:箭头函数中的 this 指向

const person = {
  name: "John",
  getName: () => {
    return this.name;
  }
};

console.log(person.getName()); // undefined

在这个栗子中,我们在对象 person 中定义了一个箭头函数 getName,并在箭头函数 getName 中使用 this 关键字来访问和修改对象 person 的属性 name。但是,箭头函数没有自己的 this 指向,它会继承其父级作用域的 this 指向。因此,在箭头函数 getName 中,this 指向全局对象 window,而对象 person 的属性 name 是不存在的,因此 this.name 会返回 undefined。

栗子 4:事件处理函数中的 this 指向

const button = document.querySelector("button");

button.addEventListener("click", function() {
  console.log(this); // button
});

在这个栗子中,我们在按钮 button 上添加了一个 click 事件监听器,并在事件监听器中使用 this 关键字来访问和修改按钮 button 的属性和方法。当我们点击按钮 button 时,事件监听器中的 this 指向按钮 button,因此我们可以通过 this 来访问和修改按钮 button 的属性和方法。

栗子 5:构造函数中的 this 指向

function Person(name) {
  this.name = name;
}

const person = new Person("John");
console.log(person.name); // "John"

在这个栗子中,我们在函数 Person 中使用 this 关键字来访问和修改对象 person 的属性 name。当我们使用 new 关键字调用函数 Person 时,会创建一个新的对象 person,并将其作为函数 Person 的 this 指向。因此,在函数 Person 中,this 指向对象 person,我们可以通过 this.name 来访问和修改对象 person 的属性 name。

栗子 6:call() 和 apply() 方法中的 this 指向

const person = {
  name: "John"
};

function getName() {
  return this.name;
}

const getName2 = getName.bind(person);
console.log(getName()); // undefined
console.log(getName2()); // "John"

在这个栗子中,我们在对象 person 中定义了一个属性 name,并在函数 getName 中使用 this 关键字来访问和修改对象 person 的属性 name。当我们调用函数 getName 时,this 指向全局对象 window,因此 this.name 会返回 undefined。

为了解决这个问题,我们可以使用 call() 或 apply() 方法来指定函数 getName 的 this 指向。当我们使用 call() 或 apply() 方法调用函数 getName 时,我们可以指定函数 getName 的 this 指向为对象 person,这样就可以通过 this.name 来访问和修改对象 person 的属性 name。

栗子 7:箭头函数中的 this 指向

const person = {
  name: "John",
  getName: () => {
    return this.name;
  }
};

console.log(person.getName()); // undefined

在这个栗子中,我们在对象 person 中定义了一个箭头函数 getName,并在箭头函数 getName 中使用 this 关键字来访问和修改对象 person 的属性 name。但是,箭头函数没有自己的 this 指向,它会继承其父级作用域的 this 指向。因此,在箭头函数 getName 中,this 指向全局对象 window,而对象 person 的属性 name 是不存在的,因此 this.name 会返回 undefined。

结语

通过这七个栗子,我们深入了解了 JavaScript 中 this 指向的奥妙。this 指向是一个非常重要的概念,但也是很多开发者头疼的问题。理解和使用 this 指向的规则,可以帮助我们在开发中避免很多问题。