使用 `call`, `apply`, `bind` 改变 JS 中 this 的指向

三葉Leaves Author

用法与区别

为了方便对比,我们用一个表格来清晰地展示它们的核心区别:

方法 作用 参数 返回值 执行时机
call() 调用函数,并指定 this thisArg, arg1, arg2, … (参数列表) 函数的执行结果 立即执行
apply() 调用函数,并指定 this thisArg, [arg1, arg2, ...] (参数数组) 函数的执行结果 立即执行
bind() 创建一个新函数,并永久绑定 this thisArg, arg1, arg2, … (参数列表) 一个绑定后的新函数 不立即执行

简单记忆法:

  • Call: 参数是 Comma-separated (逗号分隔)。
  • Apply: 参数是 Array (数组)。
  • Bind: Bound (绑定),返回一个绑定的函数,不立即执行。

巧妙用法:apply 配合 Math.max/min

Math.max()Math.min() 接受的是参数列表,而不是数组。apply 可以巧妙地将数组转换为参数列表。

  • 场景:获取数组中的最大/最小值
1
2
3
const numbers = [5, 2, 8, 1, 9];
const max = Math.max.apply(null, numbers); // this 在这里不重要,所以传入 null
console.log(max); // 9
  • 现代替代方案:扩展运算符 (...)
    扩展运算符同样可以做到,并且语法更优雅。
1
2
3
const numbers = [5, 2, 8, 1, 9];
const max = Math.max(...numbers);
console.log(max); // 9

这也是一个 apply 被现代语法替代的典型例子。

bind 的另一个用途:函数柯里化 (Partial Application)

bind 除了绑定 this,还可以预先设定函数的部分参数。

  • 场景:创建一个具有预设参数的新函数
1
2
3
4
5
6
7
8
9
function log(level, message) {
console.log(`[${level}] ${message}`);
}

// 创建一个专门用于记录错误的 log 函数
const logError = log.bind(null, 'ERROR'); // this 不重要,第一个参数是 'ERROR'

logError('Network request failed'); // 输出: [ERROR] Network request failed
logError('Invalid input'); // 输出: [ERROR] Invalid input

这种用法在创建功能更具体的工具函数时非常有用,至今仍在实践中使用。

总结

方法 核心功能 现代实践中的地位
call 立即执行,改变 this,传递参数列表 仍然用于方法借用,尤其是在一些底层库或需要兼容旧环境的代码中。日常业务中,其使用频率有所下降。
apply 立即执行,改变 this,传递参数数组 主要用于方法借用。在 Math.max 等场景下,已被更简洁的扩展运算符 (...) 替代。
bind 创建新函数,永久绑定 this 和部分参数 回调函数中固定 this 的场景,已基本被箭头函数 (=>) 全面取代。但在函数柯里化(预设参数) 方面,它依然是一个简洁实用的工具。

总而言之,call, apply, bind 仍然是每个 JS 开发者必须掌握的基础知识。但在现代前端开发中,由于 箭头函数扩展运算符 的出现,它们在某些最常见的场景下(如修复 this 指向、处理参数数组)已经有了更优雅、更推荐的替代方案。

  • 标题: 使用 `call`, `apply`, `bind` 改变 JS 中 this 的指向
  • 作者: 三葉Leaves
  • 创建于 : 2025-06-07 00:00:00
  • 更新于 : 2025-06-07 19:46:13
  • 链接: https://blog.oksanye.com/37686202c57f/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论