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

var func = function() {
  alert('hello!');
};

函数.apply();vs func.call();

上述两种方法之间是否存在性能差异?何时最好使用呼叫转移应用,反之亦然?


当前回答

让我补充一点细节。

这两个调用几乎相等:

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

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

只有一个微小的区别:

排列运算符。。。允许传递可迭代参数作为要调用的列表。apply只接受类似数组的参数。

因此,这些呼叫是相辅相成的。在我们期望可迭代的地方,调用工作,在我们期望类似数组的地方,应用工作。

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

其他回答

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

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

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

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

设Emp1={名称:'X',getEmpDetail:函数(年龄,部门){console.log(`Name:${this.Name}年龄:${Age}部门:${Department}`)}}Emp1.getEmpDetail(23,'交货')//改变“这个”的第一种方法设Emp2={名称:“Y”,getEmpDetail:Emp1.getEmpDetail}Emp2.getEmpDetail(55,“财务”)//使用“Call”和“Apply”更改“this”的第二种方法设Emp3={name:'Emp3_Object',}Emp1.getEmpDetail.call(Emp3,30,'管理员')//这里我们将ref从**Emp1更改为Emp3**对象//现在这将打印“Name=Emp3_Object”,因为它指向Emp3对象Emp1.getEmpDetail.apply(Emp3,[30,'管理员'])

调用、应用和绑定的另一个示例。Call和Apply之间的区别很明显,但Bind的工作原理如下:

Bind返回可以执行的函数的实例第一个参数是“this”第二个参数是逗号分隔的参数列表(如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
*/

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

从Function.pr原型.apply()上的MDN文档中:

apply()方法调用具有给定this值的函数作为数组(或类似数组的对象)提供的参数。语法fun.apply(thisArg,[argsArray])

从Function.pr原型.call()上的MDN文档中:

call()方法调用具有给定this值和单独提供的参数的函数。语法fun.call(thisArg[,arg1[,arg2[,…]]])

从JavaScript中的Function.apply和Function.call:

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


代码示例:

var doSomething=函数(){var arr=[];for(参数中的i){if(this〔arguments〔i〕〕的类型!==“undefined”){arr.push(this〔arguments〔i〕〕);}}返回arr;}var输出=函数(位置,对象){document.body.innerHTML+=“<h3>输出”+位置+“</h3>”+JSON.stringify(obj)+“\n<br>\n<br><hr>”;}输出(1,doSomething(“一”,“二”,“二”,“一”));输出(2,doSomething.apply({一:‘Steven’,二:‘Jane’}[“一”,“二”,“二”,“一”]));输出(3,doSomething.call({一:‘Steven’,二:‘Jane’},“一”,“二”,“二”,“一”));

另请参见此Fiddle。

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

CALL:单独提供参数的函数。若您知道要传递的参数或并没有要传递的变量,则可以使用call。

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

使用applyovercall有一个优点,我们不需要更改参数的数量,只需要更改传递的数组即可。

性能上没有太大差异。但我们可以说,调用比应用更快,因为数组需要在apply方法中求值。