Detailed Explanation of apply and call in JavaScript

  • 2021-08-05 08:25:22
  • OfStack

Differences between apply and call

The ECMAScript specification defines two methods, call and apply, for all functions. They are widely used, and their functions are 1 model and 1 sample, but the forms of parameter transmission are different.

apply( )

The apply method passes in two parameters: one is an object as the context of the function, and the other is an array of function parameters.


var obj = {
 name : 'linxin'
}
function func(firstName, lastName){
 console.log(firstName + ' ' + this.name + ' ' + lastName);
}
func.apply(obj, ['A', 'B']); // A linxin B

As you can see, obj is the object that serves as the function context, and this in the function func points to the object obj. The parameters A and B are list elements placed in an array and passed into the func function, corresponding to the func parameters, respectively.

call( )

The first parameter of the call method is also an object that serves as the function context, but a parameter list is passed in later instead of a single array.


var obj = {
 name: 'linxin'
}
function func(firstName, lastName) {
 console.log(firstName + ' ' + this.name + ' ' + lastName);
}
func.call(obj, 'C', 'D');  // C linxin D

Compared with apply, we can see the difference. C and D are passed to func function as separate parameters, instead of being put into an array.

In fact, there is no need to struggle with when and what methods should be used. If your parameters already exist in an array, then use apply, if the parameters are scattered and have no correlation with each other, use call.

Usage of apply and call

1. Change the this orientation


var obj = {
 name: 'linxin'
}
function func() {
 console.log(this.name);
}
func.call(obj);  // linxin

As we know, the first parameter of call method is the object as the function context. Here, obj is passed as a parameter to func, and this in the function points to obj object. Here, the func function is actually equivalent to


function func() {
 console.log(obj.name);
}

2. Methods to borrow from other objects

Look at the example first


var Person1 = function () {
 this.name = 'linxin';
}
var Person2 = function () {
 this.getname = function () {
  console.log(this.name);
 }
 Person1.call(this);
}
var person = new Person2();
person.getname();  // linxin

From the above, we can see that the object person instantiated by Person2 gets name in Person1 through getname method. Because in Person2, the role of Person1.call (this) is to use Person1 objects instead of this objects, Person2 has all the properties and methods in Person1, which is equivalent to Person2 inheriting the properties and methods of Person1.

3. Call a function

Both apply and call methods cause the function to execute immediately, so they can also be used to call functions.


function func() {
 console.log('linxin');
}
func.call();   // linxin

Differences between call and bind

The method called bind is extended in EcmaScript 5 and is not compatible in the lower version of IE. It is very similar to call in that it accepts two parameters, the first is an object that serves as the context of the function, and the second is a list that accepts multiple parameters.

There are two differences between them.

1. The return value of bind is a function


var obj = {
 name: 'linxin'
}
function func() {
 console.log(this.name);
}
var func1 = func.bind(obj);
func1();      // linxin

The bind method does not execute immediately, but returns a function after the context this has been changed. However, this in the original function func has not been changed, and still points to the global object window.

2. Use of parameters


function func(a, b, c) {
 console.log(a, b, c);
}
var func1 = func.bind(null,'linxin');
func('A', 'B', 'C');   // A B C
func1('A', 'B', 'C');   // linxin A B
func1('B', 'C');    // linxin B C
func.call(null, 'linxin');  // linxin undefined undefined

call passes the second and later parameters as arguments of func method, while the arguments of func1 method are actually based on the parameters in bind.

There is no bind method in lower browsers, so we can implement one ourselves.


if (!Function.prototype.bind) {
 Function.prototype.bind = function () {
  var self = this,      //  Save the original function 
   context = [].shift.call(arguments), //  Save the that needs to be bound this Context 
   args = [].slice.call(arguments); //  The remaining parameters are converted to an array 
  return function () {     //  Return 1 New functions 
   self.apply(context,[].concat.call(args, [].slice.call(arguments)));
  }
 }
}

Related articles: