apply, call
In javascript, call and apply exist to change the context (context) of a function when it runs. In other words, it is to change the direction of this inside the function body.
A major feature of JavaScript is that functions have the concepts of "definition context" and "runtime context" and "context can be changed".
Let's first get 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 redBut if we have an object banana= {color : "yellow"} , and we don't want to redefine the say method for it, then we can use the say method of apple by call or apply:
banana = {color: "yellow"}apple.say.call(banana); //My color is yellowapple.say.apply(banana); //My color is yellowTherefore, it can be seen that call and apply appear to dynamically change this. When an object does not have a certain method (banana does not say method in this chestnut), but others are (apple has a say method in this chestnut), we can use call or apply to operate it with other object methods.
The difference between apply and call
For both apply and call, the functions are exactly the same, but the methods of accepting parameters are different. For example, there is a function defined as follows:
var func = function(arg1, arg2) {};You can call it in the following way:
func.call(this, arg1, arg2);func.apply(this, [arg1, arg2])
where this is the context you want to specify, it can be any JavaScript object (everything in JavaScript is an object), call needs to pass parameters in order, and apply means to put parameters in the array.
In JavaScript, the number of parameters of a function is not fixed, so if you want to say the applicable conditions, use call when your parameters are clearly known.
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 uncertain, all parameters can also be traversed through the pseudo array of arguments inside the function.
In order to consolidate and deepen memory, the following are some common uses:
Append to arrays
var array1 = [12 , "foo" , {name "Joe"} , -2458]; var array2 = ["Doe" , 555 , 100]; Array.prototype.push.apply(array1, array2); /* array1 The value is [12 , "foo" , {name "Joe"} , -2458 , "Doe" , 555 , 100] */Get the maximum and minimum values in the array
var numbers = [5, 458 , 120 , -215 ]; var maxInNumbers = Math.max.apply(Math, numbers), //458maxInNumbers = Math.max.call(Math, 5, 458 , 120 , -215); //458
number itself does not have a max method, but Math has it, so we can use its method with call or apply.
Verify whether it is an array (provided that the toString() method has not been rewritten)
functionisArray(obj){ return Object.prototype.toString.call(obj) === '[object Array]' ;}Class (pseudo) array using array method
var domNodes = Array.prototype.slice.call(document.getElementsByTagName("*"));There is an object structure called pseudo-array in Javascript. What is more special is the arguments object, and there are also those who call getElementsByTagName, document.childNodes, etc., which return NodeList objects, all belong to pseudo-arrays. You cannot use push, pop and other methods under Array.
But we can convert Array.prototype.slice.call into a real array with the object with the length attribute, so that domNodes can apply all the methods under Array.
Deeply understand and use apply and call
Let’s borrow an interview question to understand apply and call more deeply.
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); //1The above method can solve the most basic needs, but when the number of parameters passed is uncertain, the above method will fail. At this time, you can consider using apply or call. Note that the number of parameters passed here is uncertain, so it is best to use apply. The method is as follows:
function log(){console.log.apply(console, arguments);};log(1); //1log(1,2); //1 2The next requirement is to add a "(app)" dropout to each log message, such as:
log("hello world"); //(app)hello worldHow to do it more elegantly? At this time, you need to think that the arguments parameter is a pseudo-array, which is converted into a standard array through 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 detailed explanation
After talking about apply and call, let’s talk about bind. The bind() method is very similar to apply and call, and can also change the pointing of this in the function body.
MDN's explanation is: the bind() method will create a new function, called a binding function. When this binding function is called, the binding function will use the first parameter of the bind() method when it is created as this, and the second parameter of the bind() method and the subsequent parameters plus the parameters of the binding function runtime itself 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 monomer mode, we usually use _this , that , self , etc. to save this so that we can continue to reference 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 environment has changed in eventBind:function(){ } to $('.someClass').on('click',function(event){ }). The above methods of using variables to save this 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 be called, its this keyword will be set to the value passed in (here refers to the parameters passed in when bind() is called). Therefore, here we pass in the desired context this (actually foo) into the bind() function. Then, when the callback function is executed, this points to the foo object. Another simple chestnut:
var bar = function(){console.log(this.x);}var foo = {x:3}bar(); // undefinedvar func = bar.bind(foo);func(); // 3Here we create a new function func. When using bind() to create a binding function, when it is executed, its this will be set to foo, rather than the global scope like when we call bar().
There is an interesting question. If bind() is twice in a row, or bind() is three times in a row, then 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(); //?var fiv = {x:5}var func = bar.bind(foo).bind(sed).bind(fiv);func(); //?The answer is that both times will still output 3 instead of the expected 4 and 5. The reason is that in Javascript, multiple times 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 cannot take effect.
apply, call, bind comparison
So what are the differences and differences between apply, call, and bind? When to use apply, call, and when to use bind. A simple chestnut:
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)); //81console.log(foo.getX.apply(obj)); //81console.log(foo.getX.apply(obj)); //81All three outputs are 81, but pay attention to the one using the bind() method, which has more brackets afterwards.
That is, the difference is that when you want to change the context, not execute immediately, but callbacks, use the bind() method. apply/call executes the function immediately.
Let's summarize again:
• apply , call , bind are all used to change the pointing of this object of the function;
• The first parameters of apply , call , and bind are the objects this wants to point to, that is, the context you want to specify;
•Apply, call, and bind can all use subsequent parameters to pass parameters;
•bind returns the corresponding function, which is easy to call later; apply and call are called immediately.
The above is the clever use of apply, call, and bind in Javascript introduced to you by the editor. I hope it will be helpful to you. If you have any questions, please leave me a message and the editor will reply to you in time. Thank you very much for your support to Wulin.com website!