1. 引言
你是否曾在事件回调里因为this突然变成undefined而盯着控制台发懵?又或者,在传递一个函数给setTimeout后,发现里面的this莫名其妙地指向了全局对象?这些困惑几乎每个 JavaScript 开发者都经历过——根源就在于this的指向取决于调用方式,而非定义方式。
在 JavaScript 中,this关键字的指向是一个核心且容易令人困惑的概念。为了让我们能手动控制函数执行时的上下文(即this的指向),JavaScript 提供了三个强大的方法:call、apply和bind。
本文将深入解析这三者的核心作用、关键区别、以及各自最经典的应用场景,帮助你从根本上搞定this指向,彻底告别“猜谜式”的调试体验。
📑 目录
- 1. 引言
- 2. 核心作用:改变
this指向 - 3. 核心区别:调用方式与参数格式
- 代码示例对比
- 3.1 手写实现原理
- 手写
call方法 - 手写
apply方法 - 手写
bind方法
- 手写
- 4. 经典应用场景
- 4.1
call的应用场景- 场景一:实现对象继承
- 场景二:将伪数组转换为真数组
- 4.2
apply的应用场景- 场景一:找出数组中的最大值和最小值
- 场景二:实现两个数组合并
- 4.3
bind的应用场景- 场景一:在事件处理和定时器中固定
this - 场景二:函数柯里化(部分应用)
- 场景一:在事件处理和定时器中固定
- 4.1
- 5. 性能考量与注意事项
- 5.1 性能差异
- 5.2 内存泄漏风险
- 5.3 严格模式下的
this穿透
- 6. 总结与速查
2. 核心作用:改变this指向
call、apply和bind的根本作用完全相同:改变函数运行时的this指向。
在默认情况下,一个普通函数中的this可能指向全局对象(window或global)或undefined(严格模式)。通过这三个方法,我们可以将函数内部的this明确绑定到我们指定的任何对象上,从而实现更灵活和可预测的代码逻辑。
3. 核心区别:调用方式与参数格式
虽然它们都能改变this指向,但在使用方式上有着关键的不同,这也是面试中最重要的得分点。
| 特性 | call | apply | bind |
|---|---|---|---|
| 执行时机 | 立即执行原函数 | 立即执行原函数 | 返回一个新的绑定函数,不会立即执行 |
| 第一个参数 | this要指向的新对象 | this要指向的新对象 | this要指向的新对象 |
| 后续参数 | 参数列表,逐个传递 | 参数数组或类数组,以数组形式传递 | 参数列表,逐个传递并可分次传入 |
| 返回值 | 原函数的执行结果 | 原函数的执行结果 | 一个this被永久绑定的新函数 |
下面是call、apply、bind三者在调用时机、参数传递和返回值上的执行流程对比图: