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

用法与区别
这三个函数可以被任意函数调用,也就是函数又调用了函数。
他们传入的第一个参数比较特殊,是传入一个对象之类的进去,这样调用他们三个的那个函数的内部语句的 this 环境就变成了你传进去的对象的环境了。
为了方便对比,我们用一个表格来清晰地展示它们的核心区别:
方法 | 作用 | 参数 | 返回值 | 执行时机 |
---|---|---|---|---|
call() |
调用函数,并指定 this 值 |
thisArg , arg1 , arg2 , … (参数列表) |
函数的执行结果 | 立即执行 |
apply() |
调用函数,并指定 this 值 |
thisArg , [arg1, arg2, ...] (参数数组) |
函数的执行结果 | 立即执行 |
bind() |
创建一个新函数,并永久绑定 this 值 |
thisArg , arg1 , arg2 , … (参数列表) |
一个绑定后的新函数 | 不立即执行 |
简单理解就是前两者,他们会得到函数的执行结果。比如 |
1 | Math.max.apply(null, numbers) |
就会得到 Math.max()
这个函数的执行结果。但是和直接执行这个函数的区别是:
-
对于
call()
,它可以改变 this 的指向。看上面的表格,第一个参数不是thisArg
吗?这玩意的作用是使得执行调用call
的函数的时候,函数内部语句如果用到了 this ,这个 this 指向的就是你传的那个thisArg
。这在用于处理继承问题的时候,是一种非常干净优雅的方式(其他时候倒用的不多,还不如 apply)。 -
对于
apply()
,改变 this 指向的功能和上面一样,但是特殊点在于传入的参数是一个数组,再把数组里的东西作为参数传给调用apply()
的函数。不过这玩意还真的想想就鸡肋,这不就是做了展开运算符做的事情吗? -
对于
bind()
,改变 this 指向的功能和 call() 没两样,但是得到的是一个新的函数,而不是函数的结果。这个想想就明白了,是用来制作新函数的。
简单记忆法:
- Call: 参数是 Comma-separated (逗号分隔)。
- Apply: 参数是 Array (数组)。
- Bind: Bound (绑定),返回一个绑定的函数,不立即执行。
巧妙用法:apply
配合 Math.max/min
Math.max()
和 Math.min()
接受的是参数列表,而不是数组。apply
可以巧妙地将数组转换为参数列表。
- 场景:获取数组中的最大/最小值
1 | const numbers = [5, 2, 8, 1, 9]; |
- 现代替代方案:扩展运算符 (
...
)
扩展运算符同样可以做到,并且语法更优雅。
1 | const numbers = [5, 2, 8, 1, 9]; |
这也是一个 apply
被现代语法替代的典型例子。
bind
的另一个用途:函数柯里化 (Partial Application)
bind
除了绑定 this
,还可以预先设定函数的部分参数。
- 场景:创建一个具有预设参数的新函数
1 | function log(level, message) { |
这种用法在创建功能更具体的工具函数时非常有用,至今仍在实践中使用。
总结
方法 | 核心功能 | 现代实践中的地位 |
---|---|---|
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-08-08 09:29:23
- 链接: https://blog.oksanye.com/37686202c57f/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。