Function.prototype.call()

Baseline 已广泛支持

此特性已相当成熟,可在许多设备和浏览器版本上使用。自 ⁨2015 年 7 月⁩以来,各浏览器均已提供此特性。

call() 方法用于调用一个函数,并指定函数内部 this 的值以及函数接收的参数。

试一试

function Product(name, price) {
  this.name = name;
  this.price = price;
}

function Food(name, price) {
  Product.call(this, name, price);
  this.category = "food";
}

console.log(new Food("cheese", 5).name);
// Expected output: "cheese"

语法

js
call(thisArg)
call(thisArg, arg1)
call(thisArg, arg1, arg2)
call(thisArg, arg1, arg2, /* …, */ argN)

参数

thisArg

调用 func 时要用作 this 的值。如果函数不在 严格模式 下,nullundefined 将被替换为全局对象,原始值将被转换为对象。

arg1, …, argN 可选

函数的参数。

返回值

使用指定 this 值和参数调用该函数的结果。

描述

注意: 此方法与 apply() 方法几乎相同,不同之处在于,传递给 call() 的函数参数是单独列出的,而传递给 apply() 的参数则合并到一个对象(通常是数组)中——例如,func.call(this, "eat", "bananas")func.apply(this, ["eat", "bananas"])

通常,在调用函数时,函数内部 this 的值是访问该函数的对象。通过 call(),您可以在调用现有函数时将任意值分配给 this,而无需先将函数作为属性附加到对象上。这允许您将一个对象的方法用作通用实用函数。

警告: 不要使用 call() 来链接构造函数(例如,实现继承)。这会将构造函数作为普通函数调用,这意味着 new.targetundefined,并且类会抛出错误,因为它们在没有 new 的情况下无法调用。请改用 Reflect.construct()extends

示例

使用 call() 调用函数并指定 this 值

在下面的示例中,当我们调用 greet 时,即使 greet 不是 obj 的方法,this 的值也将绑定到对象 obj

js
function greet() {
  console.log(this.animal, "typically sleep between", this.sleepDuration);
}

const obj = {
  animal: "cats",
  sleepDuration: "12 and 16 hours",
};

greet.call(obj); // cats typically sleep between 12 and 16 hours

使用 call() 调用函数而不指定第一个参数

如果省略第一个 thisArg 参数,它将默认为 undefined。在非严格模式下,this 的值将被替换为 globalThis(相当于全局对象)。

js
globalThis.globProp = "foo";

function display() {
  console.log(`globProp value is ${this.globProp}`);
}

display.call(); // Logs "globProp value is foo"

在严格模式下,this 的值不会被替换,因此它将保持为 undefined

js
"use strict";

globalThis.globProp = "foo";

function display() {
  console.log(`globProp value is ${this.globProp}`);
}

display.call(); // throws TypeError: Cannot read the property of 'globProp' of undefined

将方法转换为实用函数

call() 几乎等同于普通函数调用,不同之处在于 this 作为普通参数传递,而不是作为访问该函数的对象的属性传递。这类似于通用实用函数的工作方式:您可以使用 map(array, callback) 而不是调用 array.map(callback),这样您就可以将 map 与非数组的类数组对象(例如 arguments)一起使用,而无需修改 Object.prototype

例如,使用 Array.prototype.slice(),您希望用它将类数组对象转换为真正的数组。您可以创建一个如下的快捷方式

js
const slice = Array.prototype.slice;

// …

slice.call(arguments);

请注意,您不能保存 slice.call 并将其作为普通函数调用,因为 call() 方法还会读取其 this 值,该值是要调用的函数。在这种情况下,您可以使用 bind() 来绑定 call()this 值。在下面的代码中,slice()Function.prototype.call() 的绑定版本,其 this 值已绑定到 Array.prototype.slice()。这意味着可以消除额外的 call() 调用

js
// Same as "slice" in the previous example
const unboundSlice = Array.prototype.slice;
const slice = Function.prototype.call.bind(unboundSlice);

// …

slice(arguments);

规范

规范
ECMAScript® 2026 语言规范
# sec-function.prototype.call

浏览器兼容性

另见