前端面试题:对 this 的理解,三种改变 this 的方法

310 阅读2分钟

一、this 的理解

在 JavaScript 中,this 是一个关键字,它指向当前执行代码的上下文对象。this 的值并不是在函数定义时确定的,而是在函数被调用时动态绑定的。理解 this 的指向规则对于编写正确的 JavaScript 代码至关重要。

1.1 默认绑定

在全局作用域中,this 指向全局对象(浏览器中为 window,Node.js 中为 global)。

console.log(this); // 浏览器中输出: Window {...}

在普通函数调用中,this 也指向全局对象(非严格模式下)。

function sayHello() {
  console.log(this);
}

sayHello(); // 浏览器中输出: Window {...}

1.2 隐式绑定

当函数作为对象的方法调用时,this 指向调用该方法的对象。

const person = {
  name: "Alice",
  sayHello: function() {
    console.log(this.name);
  }
};

person.sayHello(); // 输出: Alice

1.3 显式绑定

可以使用 call()apply() 和 bind() 方法显式地改变 this 的指向。

1.4 new 绑定

使用 new 操作符调用构造函数时,this 指向新创建的对象。

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

const alice = new Person("Alice");
console.log(alice.name); // 输出: Alice

二、改变 this 的三种方法

2.1 call()

call() 方法立即调用函数,并指定函数体内 this 的值。

function sayHello(greeting) {
  console.log(greeting + ", " + this.name);
}

const person = { name: "Alice" };

sayHello.call(person, "Hello"); // 输出: Hello, Alice

2.2 apply()

apply() 方法与 call() 类似,但接收参数的方式不同,它接收一个参数数组。

function sayHello(greeting, punctuation) {
  console.log(greeting + ", " + this.name + punctuation);
}

const person = { name: "Alice" };

sayHello.apply(person, ["Hello", "!"]); // 输出: Hello, Alice!

2.3 bind()

bind() 方法创建一个新的函数,并将 this 绑定到指定的对象,但不立即执行函数。

function sayHello(greeting) {
  console.log(greeting + ", " + this.name);
}

const person = { name: "Alice" };
const sayHelloToAlice = sayHello.bind(person);

sayHelloToAlice("Hello"); // 输出: Hello, Alice

三、总结

  • this 的指向是动态的,取决于函数的调用方式。
  • 可以使用 call()apply() 和 bind() 方法显式地改变 this 的指向。
  • 理解 this 的指向规则对于编写正确的 JavaScript 代码至关重要。

四、扩展

  • 箭头函数没有自己的 this,它会继承外层函数作用域的 this
  • 在严格模式下,默认绑定的 this 为 undefined

希望这篇文章能帮助你更好地理解 JavaScript 中的 this 以及如何改变它的指向。