Understand the call, apply, bind methods in JS (transfer)

Understand the call, apply, bind methods in JS (******************************************** ****************************)





In JavaScript, call, apply and bind are three methods that come with the Function object. These three methods The main role is to change the this pointer in the function.

Common points and differences between call, apply, and bind methods:
apply , call , bind are all used to change the point of the this object of the function;
the first parameter of apply , call , bind is the object to which this points to , that is, the context you want to specify (each call of the function will have a special value - the context of this call - this is the value of the this keyword.);
apply , call , bind three can use Subsequent parameters are passed;
bind is to return the corresponding function, which is convenient to be called later; apply and call are to be called immediately.

1. call

call()
syntax:
call([thisObj[,arg1[, arg2[, [,.argN]]]]])

Definition: call a method of an object and replace the current object with another object.

Description: The call method can be used to call a method in place of another object.
The call method changes the object context of a function from the initial context to the new object specified by thisObj.

The value of thisObj has the following four situations:
(1) Do not pass, or pass null, undefined, this in the function points to the window object
(2) Pass the function name of another function, this in the function points to the reference of this function
(3) Pass a string, a value or a Boolean type and other basic types, this in the function points to its corresponding wrapper object, such as String, Number, Boolean
(4) Pass an object, and this in the function points to this object
function a(){  
  console.log(this); //Output this object in function a
}      

function b(){}      

var c={name:"call"}; //define object c 

a.call(); //window
a.call(null); //window
a. call(undefined); //window
a.call(1); //Number
a.call(''); //String
a.call(true); //Boolean
a.call(b); //function b (){}
a.call(c); //Object

If you don't understand the above, it's okay, let's look at another example:
function class1(){  
  this.name=function(){  
    console.log("I am a method in class1");  
  }  
}  
function class2(){
  class1.call(this); //After this line of code is executed, the current this points to class1 (it can also be said that class2 inherits class1 )  
}  

var f=new class2();  
f.name(); //The method in class1 is called, and the name method of class1 is handed over to class2 for use.

Common examples:
(1)
function eat(x,y){  
  console .log(x+y);  
}  
function drink(x,y){  
  console.log(xy);  
}  
eat.call(drink,3,2);

output: 5

In this example, it means to replace drink with eat , eat.call(drink,3,2) == eat(3,2) , so the running result is: console.log(5);
Note: The function in js is actually an object, and the function name is a reference to the Function object .

(2)
function Animal(){  
  this.name="animal";  
  this.showName=function(){  
    console.log(this.name);  
  }  
}  
function Dog(){  
  this.name="dog";  
}  
var animal=new Animal();  
var dog=new Dog();      

animal .showName.call(dog);

output: dog

In the above code, we can see that there is no showName method in Dog, so why is the value of (this.name) dog?

The key lies in the last piece of code (animal.showName.call(dog)), which means putting the animal's method on the dog for execution. It can also be said that the animal's showName() method is put on the dog for execution, so this.name Should be a dog.

(3) Inherit
function Animal(name){  
  this.name=name;  
  this.showName=function(){  
    console.log(this.name);  
  }  
}  
function Dog(name){  
  Animal.call(this,name);  
}  
var dog=new Dog("Crazy dog");  
dog.showName();

Output: Crazy dog

​​Animal.call(this) means to use the Animal object instead of this object, then Dog can directly call all the properties of Animal and method.

Second, apply()

syntax: apply([thisObj[,argArray]])

Definition: Apply a method of an object and replace the current object with another object.

Description:
A TypeError will be raised if argArray is not a valid array or arguments object.
If neither argArray nor thisObj are provided, the Global object will be used as thisObj and no arguments can be passed.

The difference between call and apply
For both apply and call, the functions are exactly the same, but the way of accepting parameters is different.
function class1(args1,args2){      
  this.name=function(){     
   console.log(args,args);     
  }    
}    
function class2(){   
  var args1="1";
  var args2="2";
  class1.call(this,args1,args2); 
  /* or */
  class1.apply(this,[args1,args2]);
}

var c=new class2();  
c.name();

output: 1 2

call required The parameters are passed in in order, while apply puts the parameters in an array.

Since both functions are the same, which one should I use?

In JavaScript, the number of parameters of a function is not fixed, so in terms of applicable conditions, use call when your parameters are clearly known; use apply when you are not sure, and then push the parameters into the array and pass them in . When the number of parameters is uncertain, the function can also traverse all parameters through the arguments array.

3. bind
bind is a method extended in EcmaScript5 (not supported by IE6, 7, 8) The
bind() method is very similar to apply and call, and it can also change the point of this in the function body.

  The explanation of MDN is: The bind() method will create a new function, called the binding function. When this binding function is called, the binding function will use the first parameter passed to the bind() method when it is created as this , the second and subsequent parameters passed to the bind() method plus the parameters of the binding function runtime itself are used as the parameters of the original function in order to call the original function.

Note: The return value of the bind method is the function
var bar=function(){  
  console.log(this.x);  
}
var foo={
     x:3  
}  
bar(); 
bar.bind(foo)();
/* or */
var func=bar.bind(foo);  
func();

output:
undefined
3







This article is really good Difficult to write, because there are so many related articles on the Internet.

Coincidentally, I saw a sentence from an article by Mr. Ruan a few days ago:

"For me, blogging is a knowledge management tool first, and a dissemination tool second. My technical articles are mainly used to organize my blog. I don't know the knowledge. I only write about the things I haven't fully mastered, the things I am proficient in, and often have no motivation to write. Showing off is never my motivation, curiosity is."

For this sentence, I can't agree more, It also made me determined to write this article. Although there are many articles on the Internet, most of them are copied and pasted, and they are obscure and difficult to understand. I hope that through this article, I can clearly improve my understanding of apply, call, and bind, and list some of them. The magic of deepening memory.



   apply, call


In javascript, both call and apply exist to change the context of a function's runtime, in other words, to change the point of this inside the function body.

A major feature of JavaScript is that functions have concepts such as "definition-time context" and "run-time context" and "context can be changed".

First come a chestnut:


function fruits() {}



fruits.prototype = {

    color: "red",

    say: function() {

        console.log("My color is " + this.color);

    }

}



var apple = new fruits;

apple.say(); //My color is red



but if we have an object banana= {color : "yellow"} and we don't want to redefine the say method for it, then we can use apple's say method by calling or apply:

banana = {

    color: "yellow"

}

apple .say.call(banana); //My color is yellow

apple.say.apply(banana); //My color is yellow


So, it can be seen that call and apply appear to dynamically change this, when an object does not A certain method (banana does not have a say method in this chestnut), but there are others (apple has a say method in this chestnut), we can use call or apply to operate with other object methods.



   The difference between apply and call The functions

of apply and call are exactly the same, but the way of accepting parameters is different. For example, there is a function defined as follows:


var func = function(arg1, arg2) {

    

};


can be called as follows:

func.call(this, arg1, arg2);

func.apply(this, [arg1, arg2])


where this is what you want to specify Context, it can be any JavaScript object (everything is an object in JavaScript), call needs to pass parameters in order, and apply puts parameters in an array.  

In JavaScript, the number of parameters of a function is not fixed, so to say the applicable conditions, use call when your parameters are clearly known.

And when you are not sure, use apply, and then push the parameters into the array and pass them in. When the number of parameters is uncertain, the function can also traverse all parameters through the arguments array.



In order to consolidate and deepen memory, some common usages are listed below:

1. Add


var array1 = [12 , "foo" , {name "Joe"} , -2458] between arrays;

var array2 = ["Doe" , 555 , 100] ;

Array.prototype.push.apply(array1, array2);

/* array1 value is [12 , "foo" , {name "Joe"} , -2458 , "Doe" , 555 ,






var maxInNumbers = Math.max.apply(Math, numbers), //458

    maxInNumbers = Math.max.call(Math,5, 458 , 120 , -215); //458


number itself has no max method, but Math has, We can use its methods with call or apply.

3. Verify whether it is an array (provided that the toString() method has not been overridden)


functionisArray(obj){

    return Object.prototype.toString.call(obj) === '[object Array]' ;

}


4. Class ( Pseudo) arrays use the array method


var domNodes = Array.prototype.slice.call(document.getElementsByTagName("*"));


There is an object structure in Javascript called pseudo-arrays. More special is the arguments object, as well as calling getElementsByTagName, document.childNodes and the like, they return NodeList objects are pseudo-arrays. The push, pop and other methods under Array cannot be applied.

But we can convert it to a real array object with length property through Array.prototype.slice.call, so that domNodes can apply all the methods under Array.



   In-depth understanding of the use of apply, call

Next, [borrow an interview question] to have a deeper understanding of apply and call.

Define a log method so that it can proxy the console.log method. The common solution is:

function log(msg) {

  console.log(msg);

}

log(1); //1

log(1,2); / /1


The above method can solve the most basic needs, but when the number of incoming parameters is uncertain, the above method will fail. At this time, you can consider using apply or call. Pay attention to how many parameters are passed in here. Not sure, so using apply is the best way:

function log(){

  console.log.apply(console, arguments);

};

log(1); //1

log(1,2); // 1 2


The next requirement is to add a "(app)" prefix to each log message, for example:


log("hello world"); //(app) hello world


how to do it more elegantly? This time need Think that the arguments parameter is a pseudo-array, convert it to a standard array by Array.prototype.slice.call, and then use the array method unshift, like this:

function log(){

  var args = Array.prototype.slice.call(arguments);

  args.unshift('(app)');



  console.log.apply(console, args);

};




   bind

After applying and calling, let's talk about bind. The bind() method is very similar to apply and call, and it can also change the pointer of this in the function body.

The explanation of MDN is: The bind() method will create a new function, called the binding function. When this binding function is called, the binding function will use the first parameter passed to the bind() method when it is created as this , the second and subsequent parameters passed to the bind() method plus the parameters of the binding function runtime itself are used as the parameters of the original function in order to call the original function.

Let's see how to use it directly. In the common singleton pattern, we usually use _this , that , self , etc. to save this , so that we can continue to refer to it after changing the context. Like this:


var foo = {

    bar : 1,

    eventBind: function(){

        var _this = this;

        $('.someClass').on('click',function(event) {

            /* Act on the event */

            console .log(_this.bar); //1

        });

    }

}


Due to the Javascript-specific mechanism, the context changes when eventBind:function(){ } transitions to $('.someClass').on('click',function(event) { }), and the above methods use variables to save this All are useful and no problem. Of course, using bind() can solve this problem more elegantly:

var foo = {

    bar : 1,

    eventBind: function(){

        $('.someClass').on('click',function(event) {

            /* Act on the event */

            console.log(this.bar); //1

        }.bind(this));

    }

}


In the above code, bind() creates a function that binds the click event when it is called , its this keyword will be set to the value passed in (here refers to the parameter passed in when calling bind()). So, here we pass the desired context this (actually foo ) into the bind() function. Then, when the callback function is executed, this will point to the foo object. Another simple chestnut:



var bar = function(){

console.log(this.x);

}

var foo = {

x:3

}

bar(); // undefined

var func = bar.bind(foo);

func(); // 3


here we create a new function func, which is executed when a bind function is created using bind() When it happens, its this will be set to foo instead of the global scope like when we call bar().

There is an interesting question, if you bind() twice in a row, or bind() three times in a row, what is the output value? Like this:

var bar = function(){

    console.log(this.x);

}

var foo = {

    x:3

}

var sed = {

    x:4

}

var func = bar.bind(foo).bind(sed) ;

func(); //?



var fiv = {

    x:5

}

var func = bar.bind(foo).bind(sed).bind(fiv);

func(); //?


The answer is that both times it will still output 3 instead of the expected 4 and 5. The reason is that in Javascript, multiple bind() is invalid. For a deeper reason, the implementation of bind() is equivalent to using a function to wrap a call / apply internally. The second bind() is equivalent to wrapping the first bind() again, so the bind after the second time is ineffective.

  

   Comparison of apply, call, and bind

So what are the similarities and differences between apply, call, and bind? When to use apply, call and when to use bind. Simple one:

var obj = {

    x: 81,

};



var foo = {

    getX: function() {

        return this.x;

    }

}



console.log(foo.getX.bind(obj)()); // 81

console.log(foo.getX.call(obj)); //81

console.log(foo.getX.apply(obj)); //81


The three outputs are all 81, but pay attention to the use of bind() method, he has more parentheses after it.

That is, the difference is that you use the bind() method when you want the context to be changed, not immediately, but a callback. On the other hand, apply/call executes the function immediately.



To summarize again:
•apply , call , bind are all used to change the point of the this object of the function;
•apply , call , bind The first parameter of the three is the object to be pointed to by this, that is, the context you want to specify;
•apply , call and bind can use subsequent parameters to pass parameters;
•bind is to return the corresponding function, which is convenient to call later; apply and call are to be called immediately.



This article is transferred from: http://www.cnblogs.com/coco1s/p/4833199.html

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326119069&siteId=291194637