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

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

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

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


当前回答

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

其他回答

尽管call和apply实现了相同的功能,但我认为至少有一个地方不能使用call,只能使用apply。这是您希望支持继承并希望调用构造函数的时候。

这里有一个函数允许您创建类,它也支持通过扩展其他类来创建类。

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

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

.call(范围,arg1,arg2,arg3)

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

.apply(范围,[arg1,arg2,arg3])

下面是一些更多的用法示例:http://blog.i-evaluation.com/2012/08/15/javascript-call-and-apply/

摘要:

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被记录

调用、应用和绑定的另一个示例。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允许您以数组的形式调用带有参数的函数;调用要求显式列出参数。一个有用的助记符是“A代表数组,C代表逗号。”

请参阅MDN的申请和通话文档。

伪语法:

函数.应用(值For This,arrayOfArgs)

函数调用(此值,arg1,arg2,…)

从ES6开始,还可以扩展数组以与调用函数一起使用,您可以在这里看到兼容性。

示例代码:

函数函数(名称、专业){console.log(“我的名字是”+name+“,我是”+profession+“。”);}函数(“John”,“fireman”);函数.应用(未定义,[“Susan”,“学校老师”]);函数调用(未定义,“克劳德”,“数学家”);函数调用(未定义,…[“Matthew”,“物理学家”]);//与排列运算符一起使用