Clever use of apply, call, bind in JavaScript _javascript skills

Source: Internet
Author: User

Apply, call

In JavaScript, call and apply are meant to change the context in which a function is run, in other words, to change the direction of this inside the function body.

One of the big features of JavaScript is that the function has the concept of "definition-time context" and "Run-time context" and "context is something that can be changed."

First come a chestnut:

function fruits () {}
fruits.prototype = {
color: "Red",
say:function () {
console.log ("My color is" + thi S.color);
}
var apple = new Fruits;
Apple.say (); My color is red

But if we have an object banana= {color: "Yellow"}, we do not want to redefine the say method, then we can use the Apple say method by call or apply:

Banana = {
color: "Yellow"
}
Apple.say.call (banana);//my color is yellow
apple.say.apply (banana) ; My color is yellow

So, you can see that call and apply are in order to change this dynamically, when an object does not have a method (this pest banana has no say method), but the other is (this pest Apple has say method), We can use call or apply with other object methods to manipulate.

The difference between apply and call

For apply, call both, the function is exactly the same, but the way to accept parameters is not the same. For example, there is a function defined as follows:

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

You can invoke it in the following ways:

Func.call (This, arg1, arg2);
Func.apply (This, [Arg1, arg2])

Where this is the context you want to specify, he can be any JavaScript object (everything in JavaScript), call needs to pass the parameters in order, and apply is to put the parameters in the array.

JavaScript, the number of parameters of a function is not fixed, so to say the applicable conditions, when your argument is clear to know the number of the call.

Use apply when you are unsure, and then push the parameters into the array to pass in. When the number of parameters is indeterminate, the function can also traverse all the arguments by arguments the pseudo array.

To reinforce memory, here are some common uses:

Append between arrays

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

Get the maximum and minimum values in an array

var numbers = [5, 458, -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 with Math, we can use call or apply the method.

Verify that the array (if the ToString () method has not been overridden)

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

Class (pseudo) arrays using array methods

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

There is an object structure called a pseudo array in JavaScript. More specifically, arguments objects, as well as calls to getElementsByTagName, Document.childnodes, and so on, return nodelist objects are pseudo arrays. You cannot apply a push, pop, etc method under array.

But we can convert to real arrays with the length property by Array.prototype.slice.call so that domnodes can apply all the methods under the array.

Deep understanding using Apply, call

The following is to borrow an interview question, to more in-depth understanding of apply and call.

Define a log method that allows it to proxy console.log methods, and common solutions are:

function log (msg) {
console.log (msg);
}
Log (1); 1
log (1,2);//1

The above method can solve the most basic requirements, but when the number of incoming parameters is uncertain, the above method is invalid, this time you can consider to use apply or call, note that the number of parameters passed here is uncertain, so the use of apply is the best, the method is as follows:

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, such as:

Log ("Hello World"); (APP) Hello World

What's the most elegant thing to do? This time you need to think of the arguments parameter is a pseudo array, converted to a standard array by Array.prototype.slice.call, and then using the array method Unshift, like this:

function log () {
var args = Array.prototype.slice.call (arguments);
Args.unshift (' (app) ');
Console.log.apply (console, args);
};

Bind detailed

Say, apply and call, and say bind again. The bind () method is similar to apply and call, and can also change the direction of this in a function's body.

The MDN explanation is that the bind () method creates a new function called the binding function, and when called, the binding function passes in the first argument of the bind () method when it is created, which is passed in to bind () The second and subsequent parameters of the method plus the parameters of the binding function itself are invoked as arguments to the original function in order.

Take a look directly at how to use, in the common monomer pattern, we usually use _this, that, self, and so on 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 Javascript-specific mechanisms, the context environment transitions from eventbind:function () {} to $ ('. SomeClass '). On (' click ', Function (event) {}) changed, save with variables above This is useful and there is no problem. Of course, using bind () can be a more elegant solution to this problem:

var foo = {
bar:1,
eventbind:function () {
$ ('. SomeClass '). On (' click ', Function (event) {/
* Act on The event * *
Console.log (this.bar);//1
}.bind (this));
}

In the code above, bind () creates a function that, when the Click event binding is invoked, the This keyword is set to the value passed in (this refers to the parameters passed in when bind () is invoked). So here we pass in the desired context this (in fact, Foo) into the bind () function. Then, when the callback function is executed, this points to the Foo object. One more 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, when the bind () is used to create a binding function, and when it is executed, it is set to Foo, not the global scope when we call Bar ().

The interesting question is, what is the output value if bind () two times or consecutive bind () three 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 both will still output 3, rather than the expected 4 and 5. The reason is that multiple bind () is not valid in JavaScript. For a deeper reason, the implementation of BIND () is equivalent to using a function to wrap a call/apply inside, and the second bind () is the equivalent of wrapping the first bind (), so the second bind cannot take effect.

Apply, call, bind comparison

Then apply, call, bind three compare, what is the similarities and differences between? When to use apply, call, and when to use bind. Simple one chestnut:

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

All three outputs are 81, but note that the bind () method is followed by a few pairs of parentheses.

In other words, the difference is that you use the bind () method when you want to change the context, not immediately, but when the callback executes. and Apply/call executes the function immediately.

To sum up again:

apply, call, and bind are all used to change the point of this object of the function;

apply, call, bind the first argument is the object to point to, that is, the context you want to specify;

apply, call, bind all can be used to pass the parameters of the subsequent parameter;

bind is to return the corresponding function for later invocation, and apply, call is called immediately.

The above is a small set of JavaScript to introduce you to apply, call, bind the ingenious use, hope for everyone to help, if you have any questions please give me a message, small series will promptly reply to everyone. Here also thank you very much for the cloud Habitat Community website support!

Related Article

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.