Detailed Explanation of apply and call in JavaScript
- 2021-08-05 08:25:22
- OfStack
Differences between apply and call
The ECMAScript specification defines two methods, call and apply, for all functions. They are widely used, and their functions are 1 model and 1 sample, but the forms of parameter transmission are different.
apply( )
The apply method passes in two parameters: one is an object as the context of the function, and the other is an array of function parameters.
var obj = {
name : 'linxin'
}
function func(firstName, lastName){
console.log(firstName + ' ' + this.name + ' ' + lastName);
}
func.apply(obj, ['A', 'B']); // A linxin B
As you can see, obj is the object that serves as the function context, and this in the function func points to the object obj. The parameters A and B are list elements placed in an array and passed into the func function, corresponding to the func parameters, respectively.
call( )
The first parameter of the call method is also an object that serves as the function context, but a parameter list is passed in later instead of a single array.
var obj = {
name: 'linxin'
}
function func(firstName, lastName) {
console.log(firstName + ' ' + this.name + ' ' + lastName);
}
func.call(obj, 'C', 'D'); // C linxin D
Compared with apply, we can see the difference. C and D are passed to func function as separate parameters, instead of being put into an array.
In fact, there is no need to struggle with when and what methods should be used. If your parameters already exist in an array, then use apply, if the parameters are scattered and have no correlation with each other, use call.
Usage of apply and call
1. Change the this orientation
var obj = {
name: 'linxin'
}
function func() {
console.log(this.name);
}
func.call(obj); // linxin
As we know, the first parameter of call method is the object as the function context. Here, obj is passed as a parameter to func, and this in the function points to obj object. Here, the func function is actually equivalent to
function func() {
console.log(obj.name);
}
2. Methods to borrow from other objects
Look at the example first
var Person1 = function () {
this.name = 'linxin';
}
var Person2 = function () {
this.getname = function () {
console.log(this.name);
}
Person1.call(this);
}
var person = new Person2();
person.getname(); // linxin
From the above, we can see that the object person instantiated by Person2 gets name in Person1 through getname method. Because in Person2, the role of Person1.call (this) is to use Person1 objects instead of this objects, Person2 has all the properties and methods in Person1, which is equivalent to Person2 inheriting the properties and methods of Person1.
3. Call a function
Both apply and call methods cause the function to execute immediately, so they can also be used to call functions.
function func() {
console.log('linxin');
}
func.call(); // linxin
Differences between call and bind
The method called bind is extended in EcmaScript 5 and is not compatible in the lower version of IE. It is very similar to call in that it accepts two parameters, the first is an object that serves as the context of the function, and the second is a list that accepts multiple parameters.
There are two differences between them.
1. The return value of bind is a function
var obj = {
name: 'linxin'
}
function func() {
console.log(this.name);
}
var func1 = func.bind(obj);
func1(); // linxin
The bind method does not execute immediately, but returns a function after the context this has been changed. However, this in the original function func has not been changed, and still points to the global object window.
2. Use of parameters
function func(a, b, c) {
console.log(a, b, c);
}
var func1 = func.bind(null,'linxin');
func('A', 'B', 'C'); // A B C
func1('A', 'B', 'C'); // linxin A B
func1('B', 'C'); // linxin B C
func.call(null, 'linxin'); // linxin undefined undefined
call passes the second and later parameters as arguments of func method, while the arguments of func1 method are actually based on the parameters in bind.
There is no bind method in lower browsers, so we can implement one ourselves.
if (!Function.prototype.bind) {
Function.prototype.bind = function () {
var self = this, // Save the original function
context = [].shift.call(arguments), // Save the that needs to be bound this Context
args = [].slice.call(arguments); // The remaining parameters are converted to an array
return function () { // Return 1 New functions
self.apply(context,[].concat.call(args, [].slice.call(arguments)));
}
}
}