JavaScript中call和apply的核心作用是临时改变函数执行时的this指向,实现函数借用与上下文劫持;区别仅在于call逐个传参、apply以数组传参,bind则返回永久绑定this的新函数。

JavaScript 中 call 和 apply 的核心作用是**临时改变函数执行时的 this 指向**,从而实现函数借用(复用他人方法)和上下文劫持(强制指定执行环境)。它们本质相同,区别只在参数传递方式。
函数借用:让对象“借”别人的方法用
当一个对象没有某个方法,但另一个对象有,且逻辑通用(比如数组方法处理类数组),就可以用 call 或 apply 借来用。
常见场景:
- 把类数组(如
arguments、NodeList)转成真数组并调用数组方法 - 让普通对象复用内置方法(如借用
Object.prototype.toString判断类型)
示例:
立即学习“Java免费学习笔记(深入)”;
```js
// 类数组转数组并排序
function sortArgs() {
const args = Array.prototype.slice.call(arguments); // 借 slice
return args.sort((a, b) => a - b);
}
sortArgs(3, 1, 4); // [1, 3, 4]
// 判断数据类型(避免被重写 toString 的干扰)
const type = Object.prototype.toString.call([]); // "[object Array]"
```
上下文劫持:强行指定 this,绕过默认绑定规则
函数独立调用时 this 默认是 undefined(严格模式)或全局对象(非严格),但用 call/apply 可以明确让它指向任意对象——这就是“劫持”。
关键点:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 第一个参数就是你要绑定的
this值,可以是对象、null、undefined、甚至原始值(会被自动包装) - 后续参数:`call` 逐个传,`apply` 用数组(或类数组)一次性传
示例:
立即学习“Java免费学习笔记(深入)”;
```js
const user = { name: 'Alice' };
function greet(greeting, punctuation) {
console.log(`${greeting}, ${this.name}${punctuation}`);
}
greet.call(user, 'Hello', '!'); // "Hello, Alice!"
greet.apply(user, ['Hi', '?']); // "Hi, Alice?"
```
call 与 apply 的区别和选用建议
两者功能完全一致,唯一差异是参数形式:
-
func.call(thisArg, arg1, arg2, ...)—— 参数列表展开 -
func.apply(thisArg, [arg1, arg2, ...])—— 参数封装在数组里
怎么选?
- 已知具体几个参数 → 用
call,更直观 - 参数本身是数组/类数组(比如
arguments、querySelectorAll结果)→ 用apply,免去手动展开 - ES6 后常用扩展运算符替代
apply:func(...args),但底层原理仍依赖apply思路
bind 是什么?和 call/apply 有什么关系?
bind 不是立即执行,而是返回一个新函数,该函数永久绑定指定 this 和部分参数(柯里化)。它可看作 call 的“延迟版”:
```js
const greetAlice = greet.bind(user, 'Hey');
greetAlice('.'); // "Hey, Alice."
```
而 call 和 apply 是**立即调用 + 临时绑定**,适合一次性的上下文切换。

















