In fact, many articles will write about the application and difference of Call, apply and bind, but they always feel that they are not what we want, so I summarize them myself and keep following me. I will explain the internal implementation of Call, apply and bind in detail in the future. Like can pay attention to

If there are any mistakes, please point them out in the comments so I can correct them myself

Author: thomaszhou

Use and distinguish between call, apply and bind

1, call ()

In the interview, there will be almost every js question about call, apply, bind, etc.

  • How to use call and apply to find the maximum or minimum value in an array
  • How to use call, apply to do inheritance
  • The differences and main application scenarios of Apply, Call, and bind

First of all, what are these three functions for? The answer is to change the context in which the function is executed and, more specifically, to change the this reference when the function is executed. So with that in mind, let’s see how we can use these three functions.

  let obj = {name: 'tony'};
  
  function Child(name){
    this.name = name;
  }
  
  Child.prototype = {
    constructor: Child,
    showName: function(){
      console.log(this.name);
    }
  }
  var child = new Child('thomas');
  child.showName(); // thomas
  
  //  call,apply,bindThe use of the child. ShowName. Call (obj); child.showName.apply(obj);let bind= child.showName.bind(obj); // Return a functionbind(a); // tonyCopy the code

We take someone else’s showName method, and dynamically change its context to help output information for ourselves, in the final analysis is to achieve reuse

bind

The bind method changes fn’s this to the desired result in advance, and prepares the corresponding parameter value for later use. This means that bind can also change the direction of this, but unlike apply and call, it does not execute this immediately (as in the previous example).

Note: The bind method is not compatible with IE6~8.

The difference between

It looks like the three functions are doing almost the same thing, so why have three of them? Just one of them. So what they do is essentially the same, changing this context dynamically, but there are some differences…

  • Call, apply and bind

Call and apply execute a function that changes its this context, while bind returns a function that changes its context.

  • Difference between call and apply

The difference between call and apply is in the parameters. The first parameter of call and Apply is an object to change context. Call is presented as a list of parameters starting from the second parameter.

letarr1 = [1, 2, 19, 6]; Console. log(math.max. call(null, 1,2,19,6)); // 19 console.log(Math.max.call(null, arr1)); // NaN console.log(Math.max.apply(null, arr1)); // 19 can be passed directly in with arr1Copy the code

Example 2:

function fn() { console.log(this); } // the result of the apply method is the same as fn.call(); // In normal mode this is window; in strict mode this is undefined fn.call(null); // In normal mode this is window, in strict mode this is null fn.call(undefined); // In normal mode this is window, in strict mode this is undefinedCopy the code

application

  • Convert pseudoarrays to arrays (objects with length property, DOM nodes, function arguments)

Pseudo array of js (such as through the document. The getElementsByTagName to obtain element, object containing the length attribute) has a length attribute, and can be 0, 1, 2,… To access the elements, but without the push, pop, and other methods in Array. You can use call, apply to convert to a real array, and then you can use the array methods

case1: DOM node: <div class="div1">1</div>
<div class="div1">2</div>
<div class="div1">3</div>

let div = document.getElementsByTagName('div'); console.log(div); // HTMLCollection(3) [div.div1, div.div1, div.div1] contains the length attributeletarr2 = Array.prototype.slice.call(div); console.log(arr2); // Array [div.div1, div.div1, div.div1]Copy the code

This does not apply to Internet Explorer 6~8.

SCRIPT5014: Array.prototype.slice: 'this'Not a JavaScript objectCopy the code

In IE6~8, the only way to add to an array is through a loop:

for (var i = 0; i < oLis.length; i++) {
    ary[ary.length] = oLis[i];
}
Copy the code

Based on the differences between IE6~8 and the standard browser, extract the array object into an array of utility classes:

function listToArray(likeAry) {
    var ary = [];
    try {
        ary = Array.prototype.slice.call(likeAry);
    } catch (e) {
        for(var i = 0; i < likeAry.length; i++) { ary[ary.length] = likeAry[i]; }}return ary;
}
Copy the code

Case2: Arguments within FN


function fn10() {
    returnArray.prototype.slice.call(arguments); } the console. The log (fn10 (1, 2, 3, 4, 5)); // [1, 2, 3, 4, 5]Copy the code

Note: There are no compatibility issues with the arguments borrowing array method.

Case3: object with length property

let obj4 = {
	0: 1,
	1: 'thomas', 2: 13, length: 3}; console.log(Array.prototype.slice.call(obj4)); / / [1,"thomas", 13]
Copy the code
  • Array concatenation, add
letArr1 = [1, 2, 3];letArr2 = (4 and 6); // Array concat method: returns a new arrayletarr3 = arr1.concat(arr2); console.log(arr3); // [1, 2, 3, 4, 5, 6] console.log(arr1); // [1, 2, 3] unchanged console.log(arr2); // use the apply method [].push. Apply (arr1,arr2); // Add arr2 console.log(arr1) to arr1; // [1, 2, 3, 4, 5, 6] console.log(arr2); / / the sameCopy the code
  • Judge variable types
letArr1 = [1, 2, 3];let str1 = 'string';
let obj1 = {name: 'thomas'};
//
function isArray(obj) {
  return Object.prototype.toString.call(obj) === '[object Array]';
}
console.log(fn1(arr1)); // true/ / determine type of way, this is the most useful judgment array and object, null (because the typeof null is equal to the object) console. The log (object. The prototype. ToString. Call (arr1)); // [object Array] console.log(Object.prototype.toString.call(str1)); // [object String] console.log(Object.prototype.toString.call(obj1)); // [object Object] console.log(Object.prototype.toString.call(null)); // [object Null]Copy the code
  • Use Call and apply for inheritance
function Animal(name){      
    this.name = name;      
    this.showName = function(){ console.log(this.name); }}functionCat(name){ Animal.call(this, name); } // animal.call (this) = // animal.call (this) = // animal.call (this) Var Cat = new Cat()"TONY");     
cat.showName();   //TONY
Copy the code
  • Multiple inheritance
  function Class1(a,b) {
    this.showclass1 = function(a,b) {
      console.log(`class1: ${a}.${b}`); }}function Class2(a,b) {
    this.showclass2 = function(a,b) {
      console.log(`class2: ${a}.${b}`); }}function Class3(a,b,c) {
    Class1.call(this);
    Class2.call(this);
  }

  letArr10 = (2, 2];letdemo = new Class3(); demo.showclass1.call(this,1); / / class1:1, undefined demo. Showclass1. Call (this, 1, 2); / / class1:1, 1 demo. Showclass2. Apply (this, arr10); / / class2:1, 2Copy the code