preface

In my previous article “The Principle and Usage of this”, I mentioned “Call” and “apply”.

Their main function is to change the direction of this. In my daily work, call and Apply are rarely used except when writing base classes or common library methods.

However, when suddenly encountered, it takes a moment to think before turning the corner. So today, let’s take a look at some of the differences between these two methods and some of the great uses. Finally, the bind method, which is used similarly, will be introduced.

What call and apply have in common

What they have in common is the ability to change the context in which a function is executed, handing a method from one object to another, and executing it immediately.

Why change the execution context? Take a small example in life: I have no time to cook at ordinary times, so I want to make a stew for my children at weekends. But there was no suitable pot, and I didn’t want to go out and buy one. So I asked a neighbor to borrow a pot to use, which achieved the purpose, and save money, kill two birds with one stone.

The same goes for changing the execution context. Object A has A method, and object B, for some reason, needs the same method. Should we extend A method for object B alone, or borrow A method from object A? Of course, it is borrowed from the A object, which has completed the requirements and reduced the footprint of memory.

In addition, they are written similarly. The object that calls call and apply must be a Function. Next, we’ll talk about the specific writing, which is the main manifestation of their difference.

The difference between call and apply

Their difference is mainly reflected in the writing of parameters. So let’s see how they’re written.

The call of the writing

Function call (obj, [param1 [, param2 [paramN], [...]]])Copy the code

Note the following points:

  • The object that calls call must be a Function.
  • The first argument to call is an object. The caller of Function is going to point to this object. If not, the default is the global object Window.
  • Starting with the second parameter, any parameter can be accepted. Each parameter is mapped to the Function parameter at the corresponding location. But if you pass all the parameters as an array, they are mapped as a whole to the first parameter corresponding to Function, after which the parameters are empty.
functionFunc (a,b,c) {} func. Call (obj, 1,2,3) [1,2,3]) // func is actually [1,2,3],undefined,undefinedCopy the code

The apply of writing

Function.apply(obj[,argArray])
Copy the code

Note that:

  • Its caller must be Function, and it takes only two arguments, the first of which has the same rules as call.
  • The second argument, which must be an array or an array of classes, will be converted to an array of classes, passed into Function, and mapped to the corresponding parameters of Function. This is an important distinction between call and apply.
Func. Apply (obj, {0: 1, 1: 2, 2: 3, length: {0: 1, 1: 2, 2: 3, length: {0: 1, 1: 2, 2: 3, length: 3}) // the arguments received by func are actually 1,2,3Copy the code

What is a class array?

Let’s start with arrays, which we’re all familiar with. It has the following characteristics: it can be used through the Angle label, such as array[0]; Has the length attribute length; You can do it through a for loop or through forEach.

So, what is a class array? As the name implies, objects that have similar characteristics to arrays. For example, the object below is an array of classes.

let arrayLike = {
    0: 1,
    1: 2,
    2: 3,
    length: 3
};
Copy the code

The class arrayLike can be called with a corner marker, has the Length property, and can also be traversed through a for loop.

Class array, or more commonly used, but we may not notice. For example, our method of retrieving a DOM node returns an array of classes. For example, all arguments retrieved from a method using arguments are also an array of classes.

One caveat: class arrays can’t use the methods on array prototypes like forEach, Splice, and push, because they’re not real arrays.

Use of call and apply

Here are some usage scenarios for Call and Apply. Disclaimer: There is no scenario in this example where call or apply is mandatory, just a personal habit.

Call usage scenarios

1. Object inheritance. Take the following example:

function superClass () {
    this.a = 1;
    this.print = function() { console.log(this.a); }}function subClass() { superClass.call(this); this.print(); } subClass(); / / 1Copy the code

SubClass inherits superClass’s print method and a variable via the call method. In addition, subclasses can extend other methods of their own.

2. Borrowing methods. Remember that class array? If it wants to use the methods on the Array prototype chain, it can do this:

let domNodes = Array.prototype.slice.call(document.getElementsByTagName("*"));
Copy the code

DomNodes can then apply all methods under Array.

Some of apply’s best practices

1, Math. Max. Use it to get the largest item in the array.

let max = Math.max.apply(null, array);
Copy the code

Similarly, to get the smallest item in an array, we can do this:

let min = Math.min.apply(null, array);
Copy the code

2, implement two array merge. Before the extension operators of ES6, we could use array.prototype.push.

let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];

Array.prototype.push.apply(arr1, arr2);
console.log(arr1); // [1, 2, 3, 4, 5, 6]
Copy the code

The use of the bind

Finally, bind. The bind() method creates a new function that sets the this keyword to the supplied value when called. And when the new function is called, the given parameter list is taken as the first several items of the parameter sequence of the original function.

Its syntax is as follows:

Function.bind(thisArg[, arg1[, arg2[, ...]]])
Copy the code

The bind method is similar to apply and call in that it can also change the “this” reference inside a function. The difference is that the bind method returns a function and needs to be called later before it is executed. Apply and call are immediate calls.

Consider the following example:

function add (a, b) {
    return a + b;
}

function sub (a, b) {
    returna - b; } add.bind(sub, 5, 3); // 8 add.bind(sub, 5, 3)(); // After the call, return 8Copy the code

If the first argument to bind is null or undefined, this points to the global object Window.

conclusion

The main purpose of Call and Apply is to change the execution context of an object, and to do so immediately. They are written slightly differently in terms of parameters.

Bind can also change the execution context of an object; unlike Call and apply, the return value is a function that needs to be called later before it is executed.

Finally, I would like to share a convenient method for memorizing call and apply that I have seen on Zhihu:

Cats eat fish, dogs eat meat, ultraman fights little monsters.

Tiangou wants fish

Cat eats fish. Call (dog, fish)

The dog eats the fish

The cat got clever and wanted to fight the monster

Ultraman. Beat the little Monster. Call the cat.

Cats can fight little monsters, too

PS: Welcome to follow my public account “Chao Ge Front-end Small stack” to exchange more ideas and technologies.