How to enable the use of apply, call, and bind in Javascript _ javascript skills

Source: Internet
Author: User
In Javascript, Function is an object. This in the Function object is determined by the method in which the Function is called. You can use apply, call, and bind to change the point of this in the Function object. I hope that through this article, I can clearly improve my understanding of apply, call, and bind, and list some of their advantages to deepen my memory.

Apply, call

In javascript, call and apply exist to change the context of a function running. In other words, they are used to change the point of this in the function body.

A major feature of JavaScript is that functions have the following concepts: "definition context", "RunTime context", and "context can be changed.

Here is a sample code:

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

However, if we have an object banana = {color: "yellow"} and we don't want to redefine the say method, we can use apple's say method through call or apply:

banana = {  color: "yellow"}apple.say.call(banana);   //My color is yellowapple.say.apply(banana);  //My color is yellow

Therefore, we can see that call and apply occur to dynamically change this. When an object does not have a method (banana does not have a say method in this example ), however, there are others (apple has the say method in this chestnut). We can use call or apply to operate with other object methods.

Difference between apply and call

For apply and call, the function is the same, but the method for accepting parameters is not the same. For example, a function is defined as follows:

var func = function(arg1, arg2) { };

You can call it as follows:

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

Here, this is the context you want to specify. It can be any JavaScript Object (everything in JavaScript is an object), and the call needs to pass the parameters in order, apply puts parameters in the array.

In JavaScript, the number of parameters of a function is not fixed, so if you want to apply the conditions, call is used when your parameter explicitly knows the number.

When you are not sure, use apply, and then push the parameter into the array and pass it in. When the number of parameters is unknown, the function can use the arguments array to traverse all parameters.

To consolidate and deepen the memory, the following lists some common usage:

1. appending between Arrays

Var array1 = [12, "foo", {name "Joe"},-2458]; var array2 = ["Doe", 555,100]; Array. prototype. push. apply (array1, array2);/* the value of array1 is [12, "foo", {name "Joe"},-2458, "Doe", 555,100] */

2. obtain the maximum and minimum values in the array.

var numbers = [5, 458 , 120 , -215 ]; var maxInNumbers = Math.max.apply(Math, numbers),  //458  maxInNumbers = Math.max.call(Math,5, 458 , 120 , -215); //458

Number itself does not have the max method, but Math does. We can use the call or apply method.

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

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

4. Use the array method for the class (pseudo) array

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

Javascript contains an object structure named pseudo array. Particularly, arguments objects, such as getElementsByTagName and document. childNodes, all return NodeList objects belong to pseudo arrays. The push and pop methods in Array cannot be applied.

However, we can use Array. prototype. slice. call to convert an object with the length attribute to a real Array, so that domNodes can apply all the methods in Array.

Deep understanding of using apply and call

Next we will use an interview question to better understand 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);  //1log(1,2);  //1

The above method can solve the most basic requirements, but when the number of input parameters is uncertain, the above method will be invalid. In this case, you can consider using apply or call, note that the number of parameters passed in here is uncertain, so the best way to use apply is as follows:

function log(){ console.log.apply(console, arguments);};log(1);  //1log(1,2);  //1 2

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

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

How can it be more elegant? In this case, you need to think that the arguments parameter is a pseudo Array, which is converted to a standard Array through Array. prototype. slice. call, and then unshift using the Array method, as shown in the following figure:

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 similar to apply and call, and can also change the point of this in the function body.

The explanation of MDN is that the bind () method creates a new function called the binding function. When this binding function is called, the binding function will pass in bind () when it is created () the first parameter of the method is this, and the second and later parameters of the bind () method plus the parameters of the bind function runtime are used as the parameters of the original function in order to call the original function.

Let's take a look at how to use it. In common single mode, we usually use _ this, that, self to save this, in this way, we can continue to reference it after the context is changed. 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 unique Javascript mechanism, the context transitions from eventBind: function () {} to $ ('. someClass '). on ('click', function (event) {}) has changed. The above methods of saving this with variables are useful and there is 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. When this click event is bound to a called function, its this keyword is set to the value to be passed in (here it refers to the parameter passed in when bind () is called ). Therefore, here we pass in the desired context this (actually foo) to the bind () function. Then, when the callback function is executed, this points to the foo object. Here is a simple example:

var bar = function(){console.log(this.x);}var foo = {x:3}bar(); // undefinedvar func = bar.bind(foo);func(); // 3

Here we have created a new function func. When bind () is used to create a binding function and it is executed, its this will be set to foo, instead of the global scope when bar () is called.

There is an interesting question: what is the output value if bind () is two consecutive times or three consecutive bind () times? 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 3 will be output twice, instead of 4 and 5 in expectation. The reason is that multiple bind () operations in Javascript are invalid. The deeper reason is that the implementation of bind () is equivalent to using the function to package a call/apply internally, and the second bind () is equivalent to wrapping the first bind (), the bind after the second time cannot take effect.

Comparison of apply, call, and bind

So what are the similarities and differences between apply, call, and bind? When to use apply, call, and bind. A simple example:

var obj = {  x: 81,};var foo = {  getX: function() {    return this.x;  }}console.log(foo.getX.bind(obj)()); //81console.log(foo.getX.call(obj));  //81console.log(foo.getX.apply(obj));  //81

The three outputs are 81, but note that the bind () method is used, and the parentheses are added to the end.

That is to say, the difference is that you use the bind () method when you want to change the context rather than immediately execute it, but call back for execution. The apply/call function is executed immediately.

Summary:

Apply, call, and bind are all used to change the point of this object of the function;
The first parameter of apply, call, and bind is the object to which this is to be directed, that is, the context to be specified;
Parameters apply, call, and bind can all be passed through subsequent parameters;

Bind returns the corresponding function to facilitate later call; apply and call are immediate calls.

Now, this article describes how to enable the usage mode of apply, call, and bind in Javascript.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.