Home  >  Article  >  Web Front-end  >  The uses and differences of call and apply in JavaScript

The uses and differences of call and apply in JavaScript

高洛峰
高洛峰Original
2017-01-12 11:31:131029browse

apply accepts two parameters. The first parameter specifies the pointer of this object in the function body. The second parameter is a collection with subscripts. This collection can be an array or a class array. The apply method converts this collection into The elements in are passed as parameters to the called function:

var func = function( a, b, c ){
  alert ( [ a, b, c ] ); // 输出 [ 1, 2, 3 ]
};
func.apply( null, [ 1, 2, 3 ] );

In this code, parameters 1, 2, and 3 are placed in the array and passed into the func function together. They are respectively Corresponds to a, b, c in the func parameter list.

The number of parameters passed in call is not fixed. Similar to apply, the first parameter also represents the this pointer in the function body. Starting from the second parameter, each parameter is passed into the function in turn. :

var func = function( a, b, c ){
  alert ( [ a, b, c ] ); // 输出 [ 1, 2, 3 ]
};
func.call( null, 1, 2, 3 );

When calling a function, the JavaScript interpreter does not calculate the difference in the number, type, and order of formal parameters and actual parameters. JavaScript parameters are used internally. represented by an array. In this sense, apply has a higher usage rate than call. We don't have to care about how many parameters are passed into the function, we just need to use apply to push them all. call is a syntactic sugar wrapped in apply. If we know exactly how many parameters the function accepts and want to express the correspondence between formal parameters and actual parameters at a glance, we can also use call to transfer parameters.

Uses of call and apply

1. Change this pointer

The most common use of call and apply is to change the this pointer inside the function. Let’s look at an example:

var obj1 = {
  name: 'sven'
};
var obj2 = {
  name: 'anne'
};
window.name = 'window';
var getName = function(){
  alert ( this.name );
};
getName(); // 输出: window
getName.call( obj1 ); // 输出: sven
getName.call( obj2 ); // 输出: anne

When the code getName.call(obj1) is executed, this in the getName function body points to the obj1 object, so

var getName = function(){
alert ( this.name );
};

# here ##Actually equivalent to:

var getName = function(){
alert ( obj1.name ); // 输出: sven
};

In actual development, we often encounter scenes where this pointer is inadvertently changed, such as a div node, in the onclick event of the div node this originally pointed to this div:

document.getElementById( 'div1' ).onclick = function(){
  alert( this.id ); // 输出:div1
};

If there is an internal function func in the event function, when the func function is called inside the event, this in the func function body points to the window. Instead of the div we expected, see the following code:

document.getElementById( 'div1' ).onclick = function(){
  alert( this.id ); // 输出:div1
  var func = function(){
    alert ( this.id ); // 输出:undefined
  }
  func();
};

At this time we use call to modify this in the func function so that it still points to the div:

document.getElementById( 'div1' ).onclick = function(){
  var func = function(){
    alert ( this.id ); // 输出:div1
  }
  func.call( this );
};

2. Function.prototype.bind

Most advanced browsers implement the built-in Function.prototype.bind, which is used to specify the this pointer inside the function, even if there is no native Function. prototype.bind implementation, it is not difficult for us to simulate one. The code is as follows:

Function.prototype.bind = function( context ){
var self = this; // 保存原函数
return function(){ // 返回一个新的函数
    return self.apply( context, arguments ); // 执行新的函数的时候,会   把之前传入的context
  // 当作新函数体内的this
  }
};
var obj = {
  name: 'sven'
};
var func = function(){
  alert ( this.name ); // 输出:sven
}.bind( obj);
func();

We use Function.prototype.bind to "package" the func function, and Pass in an object context as a parameter. This context object is the this object we want to modify.

In the internal implementation of Function.prototype.bind, we first save the reference to the func function and then return a new function. When we execute the func function in the future, the new function just returned is actually executed first. Inside the new function, the code self.apply(context, arguments) executes the original func function and specifies the context object as this in the body of the func function.

This is a simplified version of Function.prototype.bind implementation. Usually we will implement it a little more complicated,

so that some parameters can be pre-filled into the func function:

Function.prototype.bind = function(){
  var self = this, // 保存原函数
  context = [].shift.call( arguments ), // 需要绑定的this 上下文
  args = [].slice.call( arguments ); // 剩余的参数转成数组
  return function(){ // 返回一个新的函数
    return self.apply( context, [].concat.call( args, [].slice.call(  arguments ) ) );
    // 执行新的函数的时候,会把之前传入的context 当作新函数体内的this
    // 并且组合两次分别传入的参数,作为新函数的参数
  }
};
var obj = {
  name: 'sven'
};
var func = function( a, b, c, d ){
  alert ( this.name ); // 输出:sven
  alert ( [ a, b, c, d ] ) // 输出:[ 1, 2, 3, 4 ]
}.bind( obj, 1, 2 );
func( 3, 4 );

The above is the entire content of this article. I hope that the content of this article can bring some help to everyone's study or work. I also hope to support the PHP Chinese website!

For more articles on the uses and differences of call and apply in JavaScript, please pay attention to the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn