call 和 apply 有什么区别?

What is the difference between call and apply?

提问人:John Duff 提问时间:1/1/2010 最后编辑:MikeJohn Duff 更新时间:10/7/2023 访问量:812226

问:

使用函数和调用函数有什么区别?Function.prototype.apply()Function.prototype.call()

const func = function() {
    alert("Hello world!");
};

func.apply()HSP的func.call()

上述两种方法之间是否存在性能差异?什么时候最好使用,反之亦然?callapply

JavaScript 性能 函数 动态

评论

778赞 Larry Battle 6/12/2012
想想 in apply for array of args 和 in call for columns of args。ac
205赞 Samih 12/7/2013
@LarryBattle我几乎做同样的事情,但我认为 a 在 apply 数组和 c 在逗号的调用(即逗号分隔的参数)中。
10赞 Ringo 3/11/2014
我同意这很愚蠢。令人讨厌的是,这个问题不知何故在面试中被问到,因为一些有影响力的笨蛋将这个问题添加到了他们重要的 js 问题列表中。
13赞 Gras Double 12/4/2014
申请一份工作一次(一个论点),你[打电话]给别人很多次(几个论点)。替代方案:也有很多《使命召唤》游戏。
2赞 Ankit Singh 12/14/2016
在 ES6 中,如果你有一个参数数组,唯一的区别是三个点。即:args...fn.apply(context, args)fn.call(context, ...args)

答:

257赞 notnoop 1/1/2010 #1

K·斯科特·艾伦(K. Scott Allen)对此事有一篇很好的文章

基本上,它们在处理函数参数的方式上有所不同。

apply() 方法与 call() 相同,但 apply() 需要数组作为第二个参数。数组表示目标方法的参数。

所以:

// assuming you have f
function f(message) { ... }
f.call(receiver, "test");
f.apply(receiver, ["test"]);

评论

48赞 angry kiwi 7/29/2011
apply() 和 call() 的第二个参数是可选的,不是必需的。
40赞 Ikrom 6/5/2013
第一个参数也不是必需的。
3赞 iamcastelli 1/28/2020
@Ikrom,第一个参数不是必需的,而是callapply
4003赞 flatline 1/1/2010 #2

不同之处在于,它允许您以 as 数组的形式调用函数; 需要显式列出参数。一个有用的助记词是A 代表 rray,C 代表 comma”。applyargumentscall

请参阅 MDN 关于申请调用的文档。

伪语法:

theFunction.apply(valueForThis, arrayOfArgs)

theFunction.call(valueForThis, arg1, arg2, ...)

从 ES6 开始,还可以扩展数组以与该函数一起使用,您可以在此处查看兼容性。call

示例代码:

function theFunction(name, profession) {
    console.log("My name is " + name + " and I am a " + profession +".");
}
theFunction("John", "fireman");
theFunction.apply(undefined, ["Susan", "school teacher"]);
theFunction.call(undefined, "Claude", "mathematician");
theFunction.call(undefined, ...["Matthew", "physicist"]); // used with the spread operator

评论

33赞 Kevin Schroeder 7/29/2012
需要补充的一点是,args 必须是数值数组 ([])。关联数组 ({}) 将不起作用。
392赞 Martijn 1/10/2013
@KevinSchroeder:在javascript中,称为数组,称为对象[]{}
97赞 aziz punjani 10/7/2013
我经常忘记哪个需要数组,哪个需要你列出参数。我曾经记住的一种技术是,如果该方法的第一个字母以 a 开头,那么它需要一个数组,即一个 pply 数组
20赞 some 7/16/2014
@SAM 仅当需要更改函数调用的 this 值时,才有意义使用 call 而不是普通的函数调用。示例(将函数 arguments-object 转换为数组):或 .如果数组中有参数,例如在调用另一个具有(几乎)相同参数的函数的函数中),则 apply 是有意义的。建议如果可以满足您的需求,请使用普通的函数调用,并在您真正需要它们时保存调用申请那些特殊场合。Array.prototype.slice.call(arguments)[].slice.call(arguments)funcname(arg1)
6赞 A J Qarshi 2/24/2016
@KunalSingh 两者兼而有之,并采用两个参数。call' function 的第一个参数必须是所有者对象,第二个参数将分别是数组或逗号分隔的参数。如果将 or 作为第一个参数传递,则在非严格模式下,它们将被替换为全局对象,即callapplyapply' and nullundefinedwindow
172赞 Matthew Crumley 1/1/2010 #3

要回答有关何时使用每个函数的部分,如果您不知道将要传递的参数数量,或者它们已经在数组或类似数组的对象中(例如转发您自己的参数的对象),请使用。否则使用,因为无需将参数包装在数组中。applyargumentscall

f.call(thisObject, a, b, c); // Fixed number of arguments

f.apply(thisObject, arguments); // Forward this function's arguments

var args = [];
while (...) {
    args.push(some_value());
}
f.apply(thisObject, args); // Unknown number of arguments

当我不传递任何参数(如您的示例)时,我更喜欢,因为我正在调用该函数。 意味着您正在将该函数应用于(不存在的)参数。callapply

不应该有任何性能差异,除非你使用参数并将其包装在一个数组中(例如 而不是 )。我还没有测试过它,所以可能会有差异,但它会非常特定于浏览器。如果您还没有数组中的参数,则速度可能会更快,如果有,则速度会更快。applyf.apply(thisObject, [a, b, c])f.call(thisObject, a, b, c)callapply

98赞 kmatheny 11/8/2011 #4

虽然这是一个古老的话题,但我只是想指出 .call 比 .apply 略快。我不能告诉你确切的原因。

参见 jsPerf, http://jsperf.com/test-call-vs-apply/3


[UPDATE!]

道格拉斯·克罗克福德(Douglas Crockford)简要提到了两者之间的差异,这可能有助于解释性能差异......http://youtu.be/ya4UHuXNygM?t=15m52s

Apply 采用参数数组,而 Call 采用零个或多个单个参数!啊哈!

.apply(this, [...])

.call(this, param1, param2, param3, param4...)

评论

0赞 Eric Hodonsky 3/2/2012
这取决于函数对参数/数组的处理,如果它不需要处理数组,它需要更少的时间吗?
12赞 Josh Mc 5/11/2012
有趣的是,即使没有数组,调用速度仍然快得多。jsperf.com/applyvscallvsfn2
0赞 Vincent McNabb 10/8/2013
@JoshMc 这将是非常特定于浏览器的。在 IE 11 中,我的申请速度是通话速度的两倍。
1赞 joeytwiddle 11/24/2013
1. 创建一个新数组意味着垃圾回收器需要在某个时候清理它。2. 使用取消引用访问数组中的项目比直接访问变量(参数)效率低。(我相信这就是 kmatheny 所说的“解析”的意思,这实际上是完全不同的东西。但我的论点都没有解释 jsperf。这必须与引擎对这两个函数的实现有关,例如,如果没有传递任何函数,它们可能会创建一个空数组。
1赞 Gary 7/23/2017
感谢您分享测试和视频
24赞 user669677 7/5/2013 #5

我想举一个例子,其中使用了“valueForThis”参数:

Array.prototype.push = function(element) {
   /*
   Native code*, that uses 'this'       
   this.put(element);
   */
}
var array = [];
array.push(1);
array.push.apply(array,[2,3]);
Array.prototype.push.apply(array,[4,5]);
array.push.call(array,6,7);
Array.prototype.push.call(array,8,9);
//[1, 2, 3, 4, 5, 6, 7, 8, 9] 

**详情:http://es5.github.io/#x15.4.4.7*

126赞 Joe 9/4/2013 #6

这是一个很好的助记符。一个pply 使用 A rrays,A lways 需要一个或两个参数。当你使用 C时,你必须控制参数的数量。

评论

2赞 dantheta 11/3/2013
有用的助记符就在那里!.我将把“一个或两个参数”改为“最多两个参数”,因为第一个或第二个参数都不是必需的。我不确定为什么会调用或不调用参数。看起来有人试图找出为什么这里 stackoverflow.com/questions/15903782/......applyapplycall
7赞 Praveen D 11/6/2013 #7

我们可以区分调用和应用方法,如下所示

CALL :一个带有参数的函数,单独提供。 如果您知道要传递的参数,或者没有要传递的参数,则可以使用 call。

APPLY :调用一个函数,参数以数组形式提供。如果您不知道有多少参数将传递给函数,则可以使用 apply。

使用apply而不是调用有一个优点,我们不需要更改参数的数量,只有我们可以更改传递的数组。

性能差别不大。但是我们可以说调用比 apply 快一点,因为数组需要在 apply 方法中计算。

80赞 Dominykas Mostauskis 12/4/2013 #8

摘自迈克尔·博林(Michael Bolin)的《闭合:权威指南》(Closure: The Definitive Guide)。它可能看起来有点冗长,但它充满了很多见解。摘自“附录 B. 经常被误解的 JavaScript 概念”:


调用函数时指的是什么this

当调用 形式的函数时,该对象被称为接收方。调用函数时,接收器用作以下值:foo.bar.baz()foo.barthis

var obj = {};
obj.value = 10;
/** @param {...number} additionalValues */
obj.addValues = function(additionalValues) {
  for (var i = 0; i < arguments.length; i++) {
    this.value += arguments[i];
  }
  return this.value;
};
// Evaluates to 30 because obj is used as the value for 'this' when
// obj.addValues() is called, so obj.value becomes 10 + 20.
obj.addValues(20);

如果在调用函数时没有显式接收器,则全局对象将成为接收器。如第 47 页的“goog.global”所述,当 JavaScript 在 Web 浏览器中执行时,window 是全局对象。这导致了一些令人惊讶的行为:

var f = obj.addValues;
// Evaluates to NaN because window is used as the value for 'this' when
// f() is called. Because and window.value is undefined, adding a number to
// it results in NaN.
f(20);
// This also has the unintentional side effect of adding a value to window:
alert(window.value); // Alerts NaN

尽管 和 引用相同的函数,但它们在调用时的行为也不同,因为接收器的值在每次调用中都不同。因此,在调用引用 的函数时,重要的是要确保在调用时具有正确的值。需要明确的是,如果未在函数体中引用,则 和 的行为将是相同的。obj.addValuesfthisthisthisf(20)obj.addValues(20)

因为函数是 JavaScript 中的一类对象,所以它们可以有自己的方法。所有函数都有方法,这使得在调用函数时可以重新定义接收器(即引用的对象)。方法签名如下:call()apply()this

/**
* @param {*=} receiver to substitute for 'this'
* @param {...} parameters to use as arguments to the function
*/
Function.prototype.call;
/**
* @param {*=} receiver to substitute for 'this'
* @param {Array} parameters to use as arguments to the function
*/
Function.prototype.apply;

请注意,和 之间的唯一区别是将函数参数作为单个参数接收,而将它们作为单个数组接收:call()apply()call()apply()

// When f is called with obj as its receiver, it behaves the same as calling
// obj.addValues(). Both of the following increase obj.value by 60:
f.call(obj, 10, 20, 30);
f.apply(obj, [10, 20, 30]);

以下调用是等效的,因为 和 引用相同的函数:fobj.addValues

obj.addValues.call(obj, 10, 20, 30);
obj.addValues.apply(obj, [10, 20, 30]);

但是,由于在未指定 receiver 参数时,nor 使用其自己的 receiver 的值来替换 receiver 参数,因此以下操作将不起作用:call()apply()

// Both statements evaluate to NaN
obj.addValues.call(undefined, 10, 20, 30);
obj.addValues.apply(undefined, [10, 20, 30]);

的值 永远不能是 或 当调用函数时。当 或 作为接收器提供给 或 时,全局对象将用作接收器的值。因此,前面的代码具有相同的不良副作用,即添加一个名为全局对象的属性。thisnullundefinednullundefinedcall()apply()value

将函数视为不知道它所分配的变量可能会有所帮助。这有助于强化这样一种观点,即在调用函数时,而不是在定义函数时,将绑定此值。


提取结束。

评论

0赞 Viktor Stolbin 10/27/2015
请注意,这在正文中没有引用additionalValuesobj.addValues
0赞 jhliberty 10/26/2017
我知道你在回答这个问题,但想补充一点:你可以在定义 f 时使用 bind。 变成,现在 f(20) 可以工作,而不必每次都使用 call 或 apply。var f = obj.addValues;var f = obj.addValues.bind(obj)
1赞 Fralcon 2/7/2020
我知道它不是你写的,但你确实强调了书中的文字和例子是相关的,我非常感激。他们非常乐于助人。
13赞 Dan 12/4/2013 #9

这是一篇很小的帖子,我写过:

http://sizeableidea.com/call-versus-apply-javascript/

var obj1 = { which : "obj1" },
obj2 = { which : "obj2" };

function execute(arg1, arg2){
    console.log(this.which, arg1, arg2);
}

//using call
execute.call(obj1, "dan", "stanhope");
//output: obj1 dan stanhope

//using apply
execute.apply(obj2, ["dan", "stanhope"]);
//output: obj2 dan stanhope

//using old school
execute("dan", "stanhope");
//output: undefined "dan" "stanhope"

评论

0赞 Mark Karwowski 1/22/2014
这是另一个: blog.i-evaluation.com/2012/08/15/javascript-call-and-apply 但基本上是正确的: .call(scope, arg1, arg2, arg3)
24赞 Mark Karwowski 1/22/2014 #10

Call() 采用逗号分隔的参数,例如:

.call(scope, arg1, arg2, arg3)

apply() 接受一个参数数组,例如:

.apply(scope, [arg1, arg2, arg3])

以下是一些使用示例: http://blog.i-evaluation.com/2012/08/15/javascript-call-and-apply/

评论

0赞 xgqfrms 12/25/2016
' // call() === 逗号分隔的参数 (arguments-list) .call(this, args1, args2, args3, ...) // apply() === 参数数组 (array-items) .apply(this, [arr0, arr1, arr2, ...]) '
37赞 tjacks3 2/26/2014 #11

有时,一个对象借用另一个对象的功能很有用,这意味着借用对象只是执行借出的功能,就好像它是自己的一样。

一个小代码示例:

var friend = {
    car: false,
    lendCar: function ( canLend ){
      this.car = canLend;
 }

}; 

var me = {
    car: false,
    gotCar: function(){
      return this.car === true;
  }
};

console.log(me.gotCar()); // false

friend.lendCar.call(me, true); 

console.log(me.gotCar()); // true

friend.lendCar.apply(me, [false]);

console.log(me.gotCar()); // false

这些方法对于为对象提供临时功能非常有用。

评论

1赞 Michel Ayres 2/26/2014
对于想知道如何查看的人,请查看:什么是console.log以及如何使用它?console.log
13赞 Rakesh Kumar 2/28/2014 #12

根本区别在于它接受参数列表,而接受单个参数数组call()apply()

评论

1赞 Faraz Kelhini 3/14/2014
资料来源:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
4赞 Dhana Krishnasamy 2/13/2015 #13

即使实现同样的事情,我认为至少有一个地方你不能使用,但只能使用.也就是说,当您想要支持继承并想要调用构造函数时。callapplycallapply

这是一个允许您创建类的函数,该函数还支持通过扩展其他类来创建类。

function makeClass( properties ) {
    var ctor = properties['constructor'] || function(){}
    var Super = properties['extends'];
    var Class = function () {
                 // Here 'call' cannot work, only 'apply' can!!!
                 if(Super)
                    Super.apply(this,arguments);  
                 ctor.apply(this,arguments);
                }
     if(Super){
        Class.prototype = Object.create( Super.prototype );
        Class.prototype.constructor = Class;
     }
     Object.keys(properties).forEach( function(prop) {
           if(prop!=='constructor' && prop!=='extends')
            Class.prototype[prop] = properties[prop];
     });
   return Class; 
}

//Usage
var Car = makeClass({
             constructor: function(name){
                         this.name=name;
                        },
             yourName: function() {
                     return this.name;
                   }
          });
//We have a Car class now
 var carInstance=new Car('Fiat');
carInstance.youName();// ReturnsFiat

var SuperCar = makeClass({
               constructor: function(ignore,power){
                     this.power=power;
                  },
               extends:Car,
               yourPower: function() {
                    return this.power;
                  }
              });
//We have a SuperCar class now, which is subclass of Car
var superCar=new SuperCar('BMW xy',2.6);
superCar.yourName();//Returns BMW xy
superCar.yourPower();// Returns 2.6

评论

0赞 jhliberty 10/26/2017
我相信呼叫可以与所选答案中所述的点差运算符一起使用。除非我错过了什么。
27赞 Mahesh 3/31/2015 #14

另一个示例是 Call、Apply 和 Bind。 Call 和 Apply 之间的区别很明显,但 Bind 的工作原理是这样的:

  1. Bind 返回可执行的函数的实例
  2. 第一个参数是 'this'
  3. 第二个参数是逗号分隔的参数列表(如 Call)

}

function Person(name) {
    this.name = name; 
}
Person.prototype.getName = function(a,b) { 
     return this.name + " " + a + " " + b; 
}

var reader = new Person('John Smith');

reader.getName = function() {
   // Apply and Call executes the function and returns value

   // Also notice the different ways of extracting 'getName' prototype
   var baseName = Object.getPrototypeOf(this).getName.apply(this,["is a", "boy"]);
   console.log("Apply: " + baseName);

   var baseName = Object.getPrototypeOf(reader).getName.call(this, "is a", "boy"); 
   console.log("Call: " + baseName);

   // Bind returns function which can be invoked
   var baseName = Person.prototype.getName.bind(this, "is a", "boy"); 
   console.log("Bind: " + baseName());
}

reader.getName();
/* Output
Apply: John Smith is a boy
Call: John Smith is a boy
Bind: John Smith is a boy
*/
6赞 venkat7668 8/3/2015 #15

这些方法之间的区别在于,您希望如何传递参数。

“A 表示数组,C 表示逗号”是一个方便的助记符。

评论

13赞 Kyll 9/7/2015
这个答案提供了哪些其他答案中没有很好地提供的答案?
5赞 Raghavendra 11/24/2015 #16

调用和应用都用于在执行函数时强制执行该值。唯一的区别是接受 1 为 和 的参数。 只取两个参数,一个是参数数组,一个是参数数组。thiscalln+1this'n' argumentsapplythis

我看到的优势是,我们可以轻松地将函数调用委托给其他函数,而无需付出太多努力;applycall

function sayHello() {
  console.log(this, arguments);
}

function hello() {
  sayHello.apply(this, arguments);
}

var obj = {name: 'my name'}
hello.call(obj, 'some', 'arguments');

观察我们委托使用是多么容易,但这样做是非常困难的。hellosayHelloapplycall

20赞 John Slegers 1/18/2016 #17

来自 Function.prototype.apply() 上的 MDN 文档

apply() 方法调用具有给定值的函数,并且 参数以数组(或类似数组的对象)形式提供。this

语法

fun.apply(thisArg, [argsArray])

来自 Function.prototype.call() 上的 MDN 文档

call() 方法调用具有给定值和单独提供的参数的函数。this

语法

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

JavaScript 中的 Function.apply 和 Function.call

apply() 方法与 call() 相同,但 apply() 需要 array 作为第二个参数。数组表示 目标方法。


代码示例:

var doSomething = function() {
    var arr = [];
    for(i in arguments) {
        if(typeof this[arguments[i]] !== 'undefined') {
            arr.push(this[arguments[i]]);
        }
    }
    return arr;
}

var output = function(position, obj) {
    document.body.innerHTML += '<h3>output ' + position + '</h3>' + JSON.stringify(obj) + '\n<br>\n<br><hr>';
}

output(1, doSomething(
    'one',
    'two',
    'two',
    'one'
));

output(2, doSomething.apply({one : 'Steven', two : 'Jane'}, [
    'one',
    'two',
    'two',
    'one'
]));

output(3, doSomething.call({one : 'Steven', two : 'Jane'},
    'one',
    'two',
    'two',
    'one'
));

另请参阅此小提琴

9赞 Sanjib Debnath 8/11/2016 #18

区别在于它分别采用函数参数,并在数组中获取函数参数。call()apply()

7赞 Alireza 5/11/2017 #19

主要区别在于,使用 call,我们可以像往常一样更改范围并传递参数,但 apply 允许您使用参数作为数组来调用它(将它们作为数组传递)。但就它们在代码中要执行的操作而言,它们非常相似。

虽然此函数的语法几乎与 apply(),根本区别在于 call() 接受参数 list,而 apply() 接受单个参数数组。

所以正如你所看到的,没有太大的区别,但是,在某些情况下,我们更喜欢使用 call() 或 apply()。例如,看看下面的代码,它使用 apply 方法从 MDN 的数组中查找最小和最大的数字:

// min/max number in an array
var numbers = [5, 6, 2, 3, 7];

// using Math.min/Math.max apply
var max = Math.max.apply(null, numbers); 
// This about equal to Math.max(numbers[0], ...)
// or Math.max(5, 6, ...)

var min = Math.min.apply(null, numbers)

所以主要的区别在于我们传递参数的方式: 调用:


function.call(thisArg, arg1, arg2, ...);

应用:

function.apply(thisArg, [argsArray]);
8赞 Willem van der Veen 8/29/2018 #20

总结:

两者都是位于 上的方法。因此,它们可以通过原型链在每个函数对象上使用。两者都可以执行指定值为 的函数。call()apply()Function.prototypecall()apply()this

和 之间的主要区别在于您必须将参数传递到其中的方式。在这两个参数中,您将要作为值的对象作为第一个参数传递为 。其他参数的区别如下:call()apply()call()apply()this

  • 您必须正常输入参数(从第二个参数开始)call()
  • 有了,你必须传入参数数组。apply()

例:

let obj = {
  val1: 5,
  val2: 10
}

const summation = function (val3, val4) {
  return  this.val1 + this.val2 + val3 + val4;
}

console.log(summation.apply(obj, [2 ,3]));
// first we assign we value of this in the first arg
// with apply we have to pass in an array


console.log(summation.call(obj, 2, 3));
// with call we can pass in each arg individually

为什么需要使用这些功能?

在 javascript 中,该值有时可能很棘手。在执行函数时确定的值,而不是在定义函数时确定的值。如果我们的功能依赖于正确的绑定,我们可以使用并强制执行这种行为。例如:thisthisthiscall()apply()

var name = 'unwantedGlobalName';

const obj =  {
  name: 'Willem',
  sayName () { console.log(this.name);}
}


let copiedMethod = obj.sayName;
// we store the function in the copiedmethod variable



copiedMethod();
// this is now window, unwantedGlobalName gets logged

copiedMethod.call(obj);
// we enforce this to be obj, Willem gets logged

5赞 Pravin Divraniya 9/12/2019 #21

让我对此补充一点细节。

这两个调用几乎是等效的:

func.call(context, ...args); // pass an array as list with spread operator

func.apply(context, args);   // is same as using apply

只有一个细微的区别:

  • 操作员...允许将 Iterable 作为要调用的列表传递。spreadargs
  • 只接受类似数组的参数。apply

因此,这些呼吁是相辅相成的。我们期望一个可迭代的地方,工作,在我们期望一个类似数组的地方,工作。callapply

对于既可迭代又类似数组的对象,比如真正的数组,从技术上讲,我们可以使用其中任何一个,但应用可能会更快,因为大多数 JavaScript 引擎在内部优化得更好。

7赞 Abdul Rehman Kaim Khani 6/11/2020 #22

我只想在flatline的一篇解释良好的帖子中添加一个简单的例子,这让初学者很容易理解。

func.call(context, args1, args2 );   // pass arguments as "," separated value

func.apply(context, [args1, args2]); // pass arguments as "Array"

我们还使用“Call”和“Apply”方法来更改引用,如下面的代码中所定义

let Emp1 = {
  name: 'X',
  getEmpDetail: function(age, department) {
    console.log(`Name: ${this.name}    Age: ${age}    Department: ${department}`)
  }
}

Emp1.getEmpDetail(23, 'Delivery')

// 1st approach of changing "this"
let Emp2 = {
  name: 'Y',
  getEmpDetail: Emp1.getEmpDetail
}

Emp2.getEmpDetail(55, 'Finance')

// 2nd approach of changing "this" using "Call" and "Apply"
let Emp3 = {
  name: 'Emp3_Object',
}

Emp1.getEmpDetail.call(Emp3, 30, 'Admin')

// here we have change the ref from **Emp1 to Emp3**  object
// now this will print "Name =  Emp3_Object" because it is pointing to Emp3 object
Emp1.getEmpDetail.apply(Emp3, [30, 'Admin'])

3赞 Ran Turner 12/25/2021 #23

该方法调用具有给定值和第二个参数的函数,这些参数是用逗号分隔的参数call()this

object.someMethod.call( someObject, arguments )

该方法与 call 相同,只是它采用的第二个参数是参数数组apply()

object.someMethod.apply( someObject, arrayOfarguments )

var car  = {  
  name: "Reno",
  country: "France",
  showBuyer: function(firstName, lastName) {
    console.log(`${firstName} ${lastName} just bought a ${this.name} from ${this.country}`);
  }
}

const firstName = "Bryan";
const lastName = "Smith";

car.showBuyer(firstName, lastName);  // Bryan just bought a Reno from France

const obj = { name: "Maserati", country: "Italy" };

car.showBuyer.call(obj, firstName, lastName); // Bryan Smith just bought a Maserati from Italy

car.showBuyer.apply(obj, [firstName, lastName]); // Bryan Smith just bought a Maserati from Italy

1赞 moaz ahmad 6/28/2023 #24

在 apply() 方法中,参数以数组的形式调用,而在 call() 方法中,参数作为单独的参数单独传递

在性能方面,调用比 apply() 方法快一点,因为该方法中没有数组参数。

使用 apply() 方法,当您有类似数组的对象或实际数组时。 使用 call() 方法,当您知道参数的确切数量时,您希望传递给函数。