this、call()、apply() 和 bind() 的魔法

发布: (2026年3月15日 GMT+8 15:42)
7 分钟阅读
原文: Dev.to

I’m happy to translate the article for you, but I need the full text you’d like translated. Could you please paste the content (or the portion you want translated) here? I’ll keep the source line exactly as you provided and preserve all formatting, markdown, and code blocks.

亲爱的读者们 👋 – 欢迎回到本系列的第十篇文章

想象一下,你在派对上,有人喊道:“嘿,过来!”谁会回应?这取决于 谁在调用 以及 他们在看向谁

在 JavaScript 中,this 关键字的工作方式正是如此。它是一个特殊标识符,指向 上下文——当前 调用 函数的对象。

有时你想控制 this 指向的对象。这时神奇的三剑客 call()apply()bind() 就派上用场了。

this in JavaScript – 简明解释

  • this 是一个关键字,指向正在执行当前函数的对象。
  • 可以把它想象成一张秘密便条,告诉函数,“嘿,你现在正在为这个对象工作。”

简易规则: this 指向 调用函数的对象

this 在普通函数中的使用

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

showThis(); // 在浏览器中:记录 window 对象

当函数在全局上下文中调用时,this 指向 window

"use strict";
function showThis() {
  console.log(this);
}

showThis(); // undefined

严格模式 下,JavaScript 不会默认指向全局对象——thisundefined

记住: 在普通函数中,this 取决于函数的调用方式,而不是它的定义位置。

this 在对象内部(方法)

const person = {
  name: "Satya",
  greet() {
    console.log(`Hello, I’m ${this.name}`);
  }
};

person.greet(); // Hello, I’m Satya

当函数是对象的属性(方法)时,this 指向该对象。

当你把方法分离出来会发生什么?

const greetFn = person.greet;
greetFn(); // Hello, I’m undefined(在非严格模式下会是 window.name)

greetFn 现在是一个普通函数,所以 this 不再是 person
这时 callapplybind 就派上用场了——它们让我们 显式设置 this 的值。

call()apply()bind() – 控制 this

call()

  • 作用: 使用指定的 this 值并 逐个 传入参数来调用函数。
  • 语法: functionName.call(thisArg, arg1, arg2, …)
const person1 = { name: "Raj" };
const person2 = { name: "Priya" };

function introduce(city, country) {
  console.log(`${this.name} from ${city}, ${country}`);
}

introduce.call(person1, "Delhi", "India"); // Raj from Delhi, India
introduce.call(person2, "Mumbai", "India"); // Priya from Mumbai, India

实际例子

const car = {
  brand: "Toyota",
  getDetails(model) {
    console.log(`${this.brand} ${model}`);
  }
};

const anotherCar = { brand: "Honda" };

car.getDetails.call(anotherCar, "Civic"); // Honda Civic

我们借用了 car.getDetails,并在 anotherCar 上作为 this 调用它。

apply()

  • 作用:call() 相同,只是参数以 数组(或类数组对象)的形式提供。
  • 语法: functionName.apply(thisArg, [argsArray])
introduce.apply(person1, ["Delhi", "India"]); // Raj from Delhi, India
introduce.apply(person2, ["Mumbai", "India"]); // Priya from Mumbai, India

何时使用 apply

  • 参数已经是数组。
  • 需要传入可变数量的参数。
const numbers = [10, 20, 30, 40];
console.log(Math.max.apply(null, numbers)); // 40

(这里 this 并不重要,所以传 null。)

bind()

  • 作用: 立即调用函数。它返回一个 新函数,该函数的 this 永久绑定为提供的值(并可预先填充参数)。
  • 语法: const boundFn = functionName.bind(thisArg, arg1, arg2, …)
const person = { name: "Satya" };

function greet(greeting) {
  console.log(`${greeting}, I’m ${this.name}`);
}

const boundGreet = greet.bind(person, "Hello");
boundGreet(); // Hello, I’m Satya

实际例子

const user = {
  name: "Amit",
  sayHi() {
    console.log(`Hi, ${this.name}`);
  }
};

// 将方法传给按钮的点击处理函数
const sayHiFn = user.sayHi.bind(user);

// 以后调用 sayHiFn 时,仍然使用 `user` 作为 this
sayHiFn(); // Hi, Amit

如果不使用 bind,直接传递 user.sayHi 会导致 this 变成按钮元素(或全局对象)。

快速比较表

方法函数何时被调用?参数如何传递?典型使用场景
call()立即逐个,以逗号分隔已知参数并希望立即调用
apply()立即作为数组(或类数组)参数已经在数组中,或参数数量可变
bind()稍后(返回一个新函数)逐个(可预先填充)需要一个 this 固定的函数用于回调、事件处理等

简单助记符

  • Call – 逗号分隔的参数。
  • Apply – 数组参数。
  • Bind – 借用并绑定以供以后使用。

关键要点

  1. this 总是指向 调用函数的对象
  2. 普通函数(非方法)中,this 是全局对象(在严格模式下为 undefined)。
  3. 方法 中,this 是调用该方法的对象。
  4. call()apply() 立即调用 函数,并使用指定的 this
  5. bind() 返回一个新函数,其 this 被永久设定,可在以后调用。
  6. 当需要 逗号分隔的参数 时使用 call,需要 数组参数 时使用 apply,需要一个带固定上下文的可复用函数时使用 bind

理解 this 以及这三种方法可以帮助你避免许多 bug,并让你在控制函数执行时拥有超能力。

练习 上面的示例,尝试编写自己的代码,你会发现对 JavaScript 上下文的信心与日俱增! 🚀

很快这将成为你的第二天性。

希望你喜欢这篇博客。如果有任何错误或改进建议,欢迎告诉我。

你可以在 LinkedInX 上找到我——我会在那里发布更多内容。

0 浏览
Back to Blog

相关文章

阅读更多 »

JS 中的 this 关键字

介绍 `this` 关键字在 JavaScript 中常常让初级和高级开发者感到困惑。理解 `this` 并不取决于函数的定义位置…

现代 JS:import 和 export

封面图片:Modern JS:import and export https://media2.dev.to/dynamic/image/width=1000,height=420,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fbmf-tech...