当前位置: 首页 > article >正文

JavaScript的call和apply

在 JavaScript 中,.call().apply() 都是 Function 原型上的方法,用于改变函数执行时的上下文对象(即 this 指向),它们的区别仅在于参数传递的形式不同。下面结合几个常见场景,说明它们的实际应用。


1. 基本语法

func.call(thisArg, arg1, arg2,);
func.apply(thisArg, [arg1, arg2,]);
  • thisArg:调用时函数内部 this 应该指向的对象。
  • 参数列表call 是逗号分隔的参数序列;apply 是一个数组(或类数组)一次性传入。

2. “借用”其它对象的方法

有时候 A 对象没有某个方法,但 B 对象有,想让 A 使用 B 的方法,就可以借用:

const objA = { x: 10 };
const objB = {x: 5,getX() {return this.x;}
};console.log(objB.getX());          // 5
console.log(objB.getX.call(objA)); // 10

这里用 call(objA)getX 中的 this 强制指向 objA,就实现了“方法借用”。


3. 传递可变参数(数组转展开)

如果要把一个数组作为参数列表传给函数,用 apply 更方便:

function sum(a, b, c) {return a + b + c;
}const nums = [1, 2, 3];
console.log(sum.apply(null, nums)); // 6

等价于:

console.log(sum.call(null, nums[0], nums[1], nums[2])); // 6

在 ES6 之前,这个技巧常用于 Math.max/Math.min 获取数组最大最小值:

const arr = [5, 1, 8, 3];
const max = Math.max.apply(null, arr); // 8
const min = Math.min.apply(null, arr); // 1

ES6+ 可直接写 Math.max(...arr),但在老环境或动态参数场景下,.apply 仍然有效。


4. 构造可重用的“类”或混入(Mixin)

当多个对象需要共享同一组方法时,可以用 call/apply 在初始化时添加属性:

function Person(name) {this.name = name;
}
Person.prototype.say = function () {console.log(`Hi, I'm ${this.name}`);
};function Employee(name, company) {Person.call(this, name);  // “继承” Person 构造函数this.company = company;
}
Employee.prototype = Object.create(Person.prototype);
Employee.prototype.constructor = Employee;Employee.prototype.getCompany = function () {console.log(this.company);
};const emp = new Employee('Alice', 'Acme Inc.');
emp.say();        // Hi, I'm Alice
emp.getCompany(); // Acme Inc.

这里 Person.call(this, name)Employee 构造函数复用了 Person 的初始化逻辑。


5. 在事件处理或异步场景中绑定上下文

在回调函数中,this 往往丢失。可用 callapply 手动指定:

const obj = {value: 42,getValueAfterDelay(delay) {setTimeout(function () {// 普通函数中 this 指向全局或 undefinedconsole.log(this.value);  }.call(this), delay);}
};obj.getValueAfterDelay(1000);
// 42

不过更常用的是 .bind(this),它会返回一个新的函数:

setTimeout(function () {console.log(this.value);
}.bind(obj), 1000);

6. 小结

  • 何时用 .call()
    需要显式地将若干个独立参数逐一传入,并指定 this

  • 何时用 .apply()
    参数已经以数组或类数组形式准备好,想“一次性”传递给函数。

  • .bind() 的关系

    • call/apply 立即执行函数并指定 this
    • bind 返回一个新函数,后续调用时 this 永久绑定。

掌握了这三种方法,就可以灵活地控制函数执行的上下文,以及参数的传递方式,特别是在函数复用、混入、事件回调、动态参数等场景中非常有用。

http://www.lryc.cn/news/2387568.html

相关文章:

  • DiT、 U-Net 与自回归模型的优势
  • 开源 FcDesigner 表单设计器组件事件详解
  • Teigha应用——解析CAD文件(DWG格式)Teigha在CAD C#二次开发中的基本应用
  • C++23内存分配新特性:std::allocate_at_least
  • JavaScript性能优化全景指南
  • 04-jenkins学习之旅-java后端项目部署实践
  • 基于Python flask 的豆瓣电影top250数据评分可视化
  • Cat.4+WiFi6工业路由器介绍小体积大作用ER4200
  • 大模型应用开发第三讲:大模型是Agent的“大脑”,提供通用推理能力(如GPT-4、Claude 3)
  • 创建型模式之Abstract Factory(抽象工厂)
  • GitLab 18.0 正式发布,15.0 将不再受技术支持,须升级【一】
  • 【DeepSeek论文精读】12. DeepSeek-Prover-V2: 通过强化学习实现子目标分解的形式化数学推理
  • 字符串day7
  • vue2中,codemirror编辑器的使用
  • FastAPI与MongoDB分片集群:异步数据路由与聚合优化
  • Perl单元测试实战指南:从Test::Class入门到精通的完整方案
  • 强大的免费工具,集合了30+功能
  • 从0开始学习R语言--Day11--主成分分析
  • 通用前端框架项目静态部署到Hugging Face Space的实践指南
  • AI辅助写作 从提笔难到高效创作的智能升级
  • 十一、Samba文件共享服务
  • 医疗影像检测系统设计与实现
  • 11.13 LangGraph记忆机制解析:构建生产级AI Agent的关键技术
  • C++23中std::span和std::basic_string_view可平凡复制提案解析
  • [yolov11改进系列]基于yolov11引入感受野注意力卷积RFAConv的python源码+训练源码
  • Springboot引入Spring Cloud for AWS的配置中心(Parameter Store和Secrets)
  • 打破云平台壁垒支持多层级JSON生成的MQTT网关技术解析
  • Modbus通信中的延迟和时间间隔详解
  • maven 最短路径依赖优先
  • SAAS架构设计2-流程图-用户与租户之间对应关系图