Function.prototype.call()

Function 实例的 call() 方法使用给定的 this 值和单独提供的参数来调用此函数。

¥The call() method of Function instances calls this function with a given this value and arguments provided individually.

Try it

语法

¥Syntax

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

参数

¥Parameters

thisArg

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

arg1, …, argN Optional

函数的参数。

返回值

¥Return value

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

¥The result of calling the function with the specified this value and arguments.

描述

¥Description

注意:此函数几乎与 apply() 相同,只是函数参数作为列表单独传递给 call(),而对于 apply(),它们组合在一个对象(通常是数组)中 - 例如,func.call(this, "eat", "bananas")func.apply(this, ["eat", "bananas"])

¥Note: This function is almost identical to apply(), except that the function arguments are passed to call() individually as a list, while for apply() they are combined in one object, typically an array — for example, func.call(this, "eat", "bananas") vs. func.apply(this, ["eat", "bananas"]).

通常,当调用函数时,函数内部的 this 的值就是该函数被访问的对象。使用 call(),你可以在调用现有函数时将任意值指定为 this,而无需首先将该函数作为属性附加到对象。这允许你将一个对象的方法用作通用实用程序函数。

¥Normally, when calling a function, the value of this inside the function is the object that the function was accessed on. With call(), you can assign an arbitrary value as this when calling an existing function, without first attaching the function to the object as a property. This allows you to use methods of one object as generic utility functions.

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

¥Warning: Do not use call() to chain constructors (for example, to implement inheritance). This invokes the constructor function as a plain function, which means new.target is undefined, and classes throw an error because they can't be called without new. Use Reflect.construct() or extends instead.

示例

¥Examples

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

¥Using call() to invoke a function and specifying the this value

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

¥In the example below, when we call greet, the value of this will be bound to object obj, even when greet is not a method of 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() 调用函数而不指定第一个参数

¥Using call() to invoke a function without specifying the first argument

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

¥If the first thisArg parameter is omitted, it defaults to undefined. In non-strict mode, the this value is then substituted with globalThis (which is akin to the global object).

js
globalThis.globProp = "Wisen";

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

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

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

¥In strict mode, the value of this is not substituted, so it stays as undefined.

js
"use strict";

globalThis.globProp = "Wisen";

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

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

将方法转换为效用函数

¥Transforming methods to utility functions

call() 几乎等同于普通函数调用,只不过 this 作为普通参数传递,而不是作为访问函数的值传递。这类似于通用实用函数的工作方式:你不调用 array.map(callback),而是使用 map(array, callback),这允许你将 map 与非数组的类数组对象(例如 arguments)一起使用,而无需更改 Object.prototype

¥call() is almost equivalent to a normal function call, except that this is passed as a normal parameter instead of as the value that the function was accessed on. This is similar to how general-purpose utility functions work: instead of calling array.map(callback), you use map(array, callback), which allows you to use map with array-like objects that are not arrays (for example, arguments) without mutating Object.prototype.

Array.prototype.slice() 为例,你要使用它来将类似数组的对象转换为真正的数组。你可以创建这样的快捷方式:

¥Take Array.prototype.slice(), for example, which you want to use for converting an array-like object to a real array. You could create a shortcut like this:

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() 调用:

¥Note that you can't save slice.call and call it as a plain function, because the call() method also reads its this value, which is the function it should call. In this case, you can use bind() to bind the value of this for call(). In the following piece of code, slice() is a bound version of Function.prototype.call(), with the this value bound to Array.prototype.slice(). This means that additional call() calls can be eliminated:

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

// ...

slice(arguments);

规范

Specification
ECMAScript Language Specification
# sec-function.prototype.call

¥Specifications

浏览器兼容性

BCD tables only load in the browser

¥Browser compatibility

也可以看看