JavaScript syntax is flexible, and it is not uncommon to have five or six implementation methods for the same function. Then, coupled with some anti-human prototype inheritance and asynchronous features, it is even more confusing. I often don’t understand the difference between call and apply, so I will record it today to avoid forgetting it again.
In javascript, methods can be executed in the following ways:
1.func() is the most direct and common way of calling, and it also conforms to the thinking logic of ordinary people, but in some cases there are some shortcomings, which will be explained below.
2.(function(arg){})(window), an anonymous method call, is more useful when constructing a namespace. The parameters in the following brackets correspond to the incoming parameters in the anonymous method one by one.
3.func.bind(sth)(). The mozilla manual mentions that bind is a new feature added in ECMA-262 5th Edition. It is listed separately as a calling method because it makes up for the defect that the scope cannot be bound in direct calls.
4.func.call(), this is the second way of calling. Each method has a call method defined in the prototype to execute the current method.
5.func.apply(), call's twin brother.
func()
This is the most common way of calling and can be seen everywhere in any language. func(x, y) can pass in different parameters. In some languages, such as php, java, this kind of call is enough to solve all problems. But javascript is a functional language, and the concept of closures and a strange keyword this determine the shortcomings of this way of calling. This should be interpreted as the scope of the current code segment, which will change as the code executes to different fragments. However, in some cases we do not want this to be changed, such as events bound to certain doms. We definitely do not want this to be transferred to the window object when they are called, but sometimes this is true, for example, the following code.
The code copy is as follows:
var a ={};
var func = function(x) {
console.log(this);
};
a.onclick = function() {
var x = 100;
func(x);
};
a.onclick();
You can think of a as a link in the page. Since we just want to bind the defined method to the onclick event instead of calling it immediately, and this method has a parameter, we need to wrap it up with an anonymous method and pass it to the onclick event of a. This has a problem. This in func becomes the global object window, obviously we don't want this. At this time, using func() as a direct call method is not possible, so we need to bind this outside of func to the func method. So there is a bind, call, apply method.
bind
The purpose of bind is very simple, returning the same method that binds this object. The above code can achieve the purpose of binding this on the a object by modifying one line.
The code copy is as follows:
var a ={};
var func = function(x) {
console.log(this);
};
a.onclick = function() {
var x = 100;
func.bind(this)(x); // bind here
};
a.onclick();
In this way, this onclick event will not run around like a headless fly.
call & apply
Call and apply should be talked about together because they are so similar. They all support multiple parameters, and the first parameter is this object that will be bound to, and the second parameter is their difference. Call uses independent parameters as invocation parameters, and apply uses an array as invocation parameters. Sometimes we don’t want to change this object, but we want to artificially bind it to other objects. At this time, call and apply are very useful. (It's not that you can't use bind, but it seems that bind appears late, so the browser compatibility may be poor). Take a chestnut:
The code copy is as follows:
a = {
func: function() {
this.x += 1;
},
x: 0
};
b = {
a: a,
x: 20
};
for(var i = 0; i < 10; i++){
bafunc();
}
console.log(ax);
console.log(bx);
There are x in the a and b objects above. We hope that func can modify the corresponding x in a targeted manner, but direct call can only modify x in the func scope, that is, ax. Modify the code to achieve the purpose of modifying bx
The code copy is as follows:
a = {
func: function() {
this.x += 1;
},
x: 0
};
b = {
a: a,
x: 20
};
for(var i = 0; i < 10; i++){
bafunc.call(b); // bind this to b
}
console.log(ax);
console.log(bx);
This chestnut is not well-received, and it is a very confusing code style, with applicable scenarios, but not available everywhere.