巧记 call, apply, bind 的实现

用法简介

在 JavaScript 中,call, apply, 和 bind 都是用来改变函数内部 this 指向的工具。

  • call: 立即调用函数,参数逐个传递。 函数.call(想绑定的this, arg1, arg2, ...)

  • apply: 立即调用函数,参数以数组形式传递。 函数.apply(想绑定的this, [arg1, arg2, ...])

  • bind: 不立即调用,而是返回一个绑定了 this 的新函数,可稍后调用。 新函数 = 函数.bind(想绑定的this, arg1, ...)


实现方式

call, apply, 和 bind 的实现魔法,都基于同一个简单而强大的思想:将函数“嫁接”到目标对象上,再以方法的形式调用它。

想象一下,我们想让 fn 这个函数在 targetObject 的上下文中执行(即让 fn 内部的 this 指向 targetObject)。

只需三步,即可记住它们的共同实现原理:

第一步:挂载(嫁接)

将要执行的函数 fn,变成目标对象 targetObject 的一个临时属性。为了防止覆盖掉 targetObject 已有的同名属性,我们会用一个独一无二的名字(比如 Symbol)来命名这个临时属性。

// 假设 fn 是我们要执行的函数
// 假设 targetObject 是我们想绑定的 this

const uniqueKey = Symbol(); // 创建一个独一无二的钥匙
targetObject[uniqueKey] = fn; // 把 fn 函数挂载到目标对象上

理解: 此时,fn 已经成为了 targetObject 的一个方法,就像 targetObject.name 是它的属性一样。

第二步:调用

直接通过 targetObject 来调用这个刚刚挂载的临时方法。根据 JavaScript 的规则,当一个函数作为对象的方法被调用时,其内部的 this 自动指向该对象。这样,this 绑定的目的就达到了!

// 调用这个临时方法,并把参数传进去
// `...args` 代表了 call/apply 传递进来的参数
const result = targetObject[uniqueKey](...args);

理解: 执行 targetObject[uniqueKey]() 时,fn 内部的 this 就百分之百是 targetObject

第三步:卸载(清理)

函数已经执行完毕,我们不应该修改原始的 targetObject。因此,需要把刚才添加的临时属性删掉,恢复 targetObject 的原貌。

// 执行完毕后,删除这个临时属性,不留痕跡
delete targetObject[uniqueKey];

理解: “事了拂衣去,深藏功与名”。目标对象恢复原样,但我们已经拿到了函数的执行结果。


总结

  • callapply 的实现,就是完整地执行上述“挂载 -> 调用 -> 卸载”三步曲,并立即返回结果。它们的唯一区别只在于第二步“调用”时传递参数的方式不同。

  • bind 的实现,则是创建了一个新的函数,这个新函数封装了“挂载 -> 调用 -> 卸载”的逻辑,以便在将来被调用时执行。

记住这个核心的三步流程,你就能从根本上理解这三个方法是如何工作的,再也不会混淆它们。

Copyright © Jun 2025 all right reserved,powered by Gitbook该文件修订时间: 2025-07-03 17:35:08

results matching ""

    No results matching ""

    results matching ""

      No results matching ""