JavaScript中call与apply的核心差异与继承应用

一颗松果
一颗松果
发布时间:2026-10-14| 2人浏览过
原创

在JavaScript中,call 和 apply 是改变函数执行上下文(即 this 指向)的核心工具,二者功能相似但参数传递方式不同。本文将详解其语法结构、this 指向逻辑以及在对象继承中的应用,帮助开发者理清概念,避免参数格式错误。

核心定义与语法结构

call() 方法在使用一个指定的 this 值和若干个指定的参数值的前提下调用某个函数或方法。它与 apply() 作用类似,唯一区别在于参数接收形式:call 接受逐个列出的参数,而 apply 接受一个包含多个参数的数组。

语法如下:

fun.call(thisArg[, arg1[, arg2[, ...]]]) 
fun.apply(thisArg, [argsArray])

this 指向机制与非严格模式行为

thisArg 是在函数运行时指定的上下文对象。理解这一概念的关键在于:this 的值由函数的调用方式决定,而非定义位置。

  • 显式绑定:当使用 call 或 apply 时,this 将指向传入的第一个参数。
  • 非严格模式陷阱:若指定为 null 或 undefined,this 会自动指向全局对象(浏览器中为 window)。此外,原始值(数字、字符串、布尔值)会被自动包装为对应的对象实例。

第1步:验证 this 指向变化

目的是观察当 thisArg 改变时,函数内部属性访问的变化。入口为控制台代码片段,动作是定义对象与函数并执行调用,参数为不同的对象引用。

 var p = "456";
 function f1() {
  this.p = "123";
 }
 function f2() {
  console.log(this.p);
 }
 f2();           // 输出: 456 (全局变量)
 f2.call(f1());  // 输出: 123 (f1的对象属性)
 f2.apply(f1()); // 输出: 123 (f1的对象属性)

第一次调用直接输出全局变量 p。后续因使用了 call 和 apply,f2 中的 this 被重定向至 f1 的实例,从而读取到其自身定义的属性。这种“借用”方法是实现面向对象中继承的一种手段。

注意:若移除 f1 中的 this.p,输出将恢复为三个 456,这证实了当绑定对象无该属性且未定义时,回退机制会寻找全局变量。

第2步:利用 call 实现属性继承

既然能借用方法,同样可以借用构造函数中的属性赋值,从而实现浅层继承。动作是将 call 置于子构造函数内。

 function f1() {
  this.father = "father";
 }
 function f2() {
  f1.call(this); // 将 f1 的执行上下文绑定到当前 f2 实例
  this.child = "child";
 }
var test = new f2();
console.log(test.father); // 输出: father

在 f2 内部执行 f1.call(this) 时,this 指向正在创建的 f2 实例。因此,f1 对 this 的属性赋值操作,实际上是为 f2 的新实例添加了属性。这是基于构造函数模式的经典继承写法。

参数传递的关键区别

call 和 apply 的主要差异体现在剩余参数上。call 逐个接收参数,apply 必须接收一个数组作为第二参数。

第3步:测试参数传递差异

目的是对比正确与错误的参数格式,观察控制台输出或报错信息。入口为定义带参数的函数,动作是分别以不同格式传入参数。

 function f1(){ this.p = "测试call"; }
 function f2(x, y, z) {
  console.log(this.p); 
  console.log(x); 
  console.log(y); 
  console.log(z);
 }
 function f3(){ this.p = "测试apply"; }
 
 // 测试1: call 逐个传参 (成功)
 f2.call(f1(), 4, 5, 6);  
 
 // 测试2: call 传入数组 (失败)
 f2.call(f1(), [4, 5, 6]);  
 
 // 测试3: apply 传入数组 (成功)
 f2.apply(f3(), [4, 5, 6]); 
 
 // 测试4: apply 逐个传参 (失败)
 f2.apply(f3(), 4, 5, 6);

根据执行结果分析:

  • 第一段:call 正常接收 4, 5, 6 作为独立参数,输出符合预期。
  • 第二段:call 将 [4, 5, 6] 视为第一个参数 x,导致 y 和 z 为 undefined。
  • 第三段:apply 正确解析数组内的元素,分别赋给 x, y, z。
  • 第四段:apply 严格要求第二个参数为数组或类数组对象,直接传入逗号分隔的值会抛出语法错误。

简要总结

call 和 apply 是 JavaScript 高级特性的基石,主要用于控制 this 指向和实现函数复用。记住口诀:Call 后面跟着参数序列,Apply 后面跟着一个数组。在实际开发中,常结合 Function.prototype.bind 或箭头函数来处理复杂的事件回调,但掌握底层原理有助于调试深层 bug。以上就是 JavaScript 中 call 与 apply 的详细解析,更多关于前端基础进阶的资料请关注本站其它相关文章!

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。