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

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

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

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


当前回答

调用、应用和绑定的另一个示例。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
*/

其他回答

主要的区别是,使用调用,我们可以改变作用域并按正常方式传递参数,但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]);

K.Scott Allen对这件事有很好的评论。

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

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

So:

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

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

object.someMethod.call( someObject, arguments )

apply()方法与调用相同,只是它使用的第二个参数是一个参数数组。

object.someMethod.apply( someObject, arrayOfarguments )

var汽车={name:“雷诺”,国家:“法国”,showBuyer:函数(firstName,lastName){console.log(`${firstName}${lastName}刚刚从${this.country}购买了${this.name});}}const firstName=“Bryan”;const lastName=“Smith”;car.showBuyer(firstName,lastName);//布莱恩刚从法国买了一辆雷诺constobj={name:“玛莎拉蒂”,国家:“意大利”};car.showBuyer.call(obj,firstName,lastName);//布莱恩·史密斯刚从意大利买了一辆玛莎拉蒂car.showBuyer.apply(obj,[firstName,lastName]);//布莱恩·史密斯刚从意大利买了一辆玛莎拉蒂

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

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


[更新!]

Douglas Crockford简要提到了两者之间的差异,这可能有助于解释性能差异。。。http://youtu.be/ya4UHuXNygM?t=15m52s

Apply接受一个参数数组,而Call接受零个或多个单独的参数!啊哈!

.apply(此,[…])

.调用(this,param1,param2,param3,param4…)

摘要:

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

call()和apply()之间的主要区别是必须向其中传递参数的方式。在call()与apply(()中,您都将希望作为值的对象作为第一个参数传递为this。其他参数的不同之处如下:

使用call(),您必须正常输入参数(从第二个参数开始)使用apply(),必须传入参数数组。

例子:

让obj={val1:5,值2:10}常量总和=函数(val3,val4){返回this.val1+this.val2+val3+val4;}console.log(summary.apply(obj,[2,3]));//首先,我们在第一个参数中为其赋值//使用apply,我们必须传入一个数组console.log(summary.call(obj,2,3));//通过调用,我们可以单独传入每个参数

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

在javascript中,这个值有时很棘手。该值在执行函数时确定,而不是在定义函数时确定。如果我们的函数依赖于此绑定的权限,我们可以使用call()和apply()来强制执行此行为。例如:

var name='unwantedGlobalName';常量对象={name:“Willem”,sayName(){console.log(this.name);}}let copiedMethod=obj.sayName;//我们将函数存储在copiedmethod变量中copiedMethod();//现在是窗口,unwantedGlobalName将被记录copiedMethod.call(obj);//我们强制这是obj,Willem被记录