学习 JavaScript 中的 call、apply 和 bind:初学者指南 🚀

了解“this”关键字的工作原理是 JavaScript 的基础。“this”的值会根据函数的调用方式而变化。有时,我们需要显式设置“this”以引用特定对象。这就是方法“call”、“apply”和“bind”的用武之地。这些强大的方法让我们可以控制“this”的值,这使得它们对于掌握 JavaScript 函数和面向对象编程至关重要。

在这篇博客中,我们将详细探讨这些方法并讨论它们的现代意义。🖥️

JavaScript 中的 this 是什么?🤔

在深入研究“call”、“apply”和“bind”之前,让我们先简单讨论一下**这个**。

`this` 指的是函数被调用的上下文。其值可以根据函数的调用方式而改变:

  • 在常规函数调用中,this 指的是全局对象(在浏览器中,它是窗口)。
  • 在方法调用中,this 指的是拥有该方法的对象。
  • 在事件处理程序中,这指的是触发事件的 DOM 元素。
  • 现在,让我们看看如何使用 `call`、`apply` 和 `bind` 来控制这个上下文。🌍

    1. call 方法:立即调用⚡

    `call` 方法允许您调用一个函数并明确将 `this` 的值设置为特定对象。参数**单独**传递。

    句法:

    func.call(thisArg, arg1, arg2, ...);
  • thisArg:您希望此值引用。
  • arg1、arg2、...:传递给函数的参数。
  • 例子:

    const person = {
      name: 'Alice',
    };
    
    function greet() {
      console.log(`Hello, ${this.name}!`);
    }
    
    greet.call(person);  // Output: Hello, Alice!

    为什么要使用呼叫?

    当从一个对象借用方法或者想要使用自定义上下文立即调用函数时,`call` 很有用。🔄

    2.apply 方法:参数作为数组🗣️

    `apply` 方法与 `call` 类似,但不是单独传递参数,而是将它们作为**数组**传递。

    句法:

    func.apply(thisArg, [arg1, arg2, ...]);
  • thisArg:此的值。
  • [arg1, arg2, ...]:参数数组。
  • 例子:

    const person = {
      name: 'Bob',
    };
    
    function introduce(greeting, punctuation) {
      console.log(`${greeting}, ${this.name}${punctuation}`);
    }
    
    introduce.apply(person, ['Hi', '!']);  // Output: Hi, Bob!

    为什么要使用apply?

    当你需要动态传递参数数组时,`apply` 很有用。📆

    3. bind 方法:创建一个新函数

    `bind` 方法返回一个具有固定 `this` 值和可选预设参数的 **新函数**。与 `call` 和 `apply` 不同,它不会立即调用该函数。

    句法:

    const boundFunc = func.bind(thisArg, arg1, arg2, ...);
  • thisArg:要绑定的值。
  • arg1,arg2,...:绑定函数中预设的可选参数。
  • 例子:

    const person = {
      name: 'Charlie',
    };
    
    function greet() {
      console.log(`Hello, ${this.name}!`);
    }
    
    const boundGreet = greet.bind(person);
    boundGreet();  // Output: Hello, Charlie!

    为什么要使用 bind?

    当你需要确保函数始终使用特定上下文时,`bind` 很有用,即使它作为回调传递(例如,在事件侦听器中)。🕰

    call、apply 和 bind 之间的主要区别

    何时使用每种方法?📜

  • 在使用特定 this 调用函数并单独传递参数时使用 call。🔟
  • 在使用特定 this 调用函数并将参数作为数组传递时使用 apply。🏟️
  • 创建新函数时使用 bind,以便以后使用。🔧
  • call、apply 和 bind 在现代 JavaScript 中仍然有用吗?🤔

    箭头函数、spread/rest 语法和函数式编程范式等现代 JavaScript 功能在某些情况下减少了对这些方法的需求。但是,**call、apply 和 bind** 仍然适用于:

  • 动态上下文绑定:为借用的方法或动态参数明确设置此项。
  • 使用遗留代码:旧的代码库通常广泛使用这些方法。
  • 函数可重用性:创建具有特定上下文的可重用函数。
  • 与现代替代品的比较

  • 箭头函数:根据词法范围自动绑定 this,但缺乏手动控制 this 的灵活性。
  • 扩展语法(...):简化参数处理,但不能替代自定义上下文的应用。
  • 示例:扩展语法与应用语法

    const numbers = [1, 2, 3, 4];
    
    // Using apply
    const max1 = Math.max.apply(null, numbers);
    
    // Using spread
    const max2 = Math.max(...numbers);
    
    console.log(max1 === max2);  // Output: true

    练习题📝

  • 以下代码的输出是什么? const person = { name: 'John' }; functiongreet(message) { console.log(`${message}, ${this.name}`); }greet.call(person, 'Hello'); // 输出?
  • call 和 apply 之间的区别:什么时候你会更喜欢其中一个?请举例说明。
  • 以下代码的结果是什么? const person = { name: 'Jane' }; function sayHello() { console.log(`Hello, ${this.name}`); } const boundSayHello = sayHello.bind(person); boundSayHello(); // 输出?
  • bind 可以像 call 或 apply 一样立即传递参数吗?为什么或为什么不可以?
  • 使用绑定进行事件处理:在事件监听器中使用绑定编写一个示例。
  • 结论

    理解 `call`、`apply` 和 `bind` 是掌握 JavaScript 的关键。这些方法让你可以控制 `this` 上下文,让你可以编写灵活且可重用的代码。虽然现代 JavaScript 引入了替代方案,但这些方法在许多情况下仍然不可或缺。祝你编码愉快!🚀