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 ); };
var getName = function(){ alert ( obj1.name ); // 输出: sven };
document.getElementById( 'div1' ).onclick = function(){ alert( this.id ); // 输出:div1 };
document.getElementById( 'div1' ).onclick = function(){ alert( this.id ); // 输出:div1 var func = function(){ alert ( this.id ); // 输出:undefined } func(); };
document.getElementById( 'div1' ).onclick = function(){ var func = function(){ alert ( this.id ); // 输出:div1 } func.call( this ); };
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();
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 );