call 和apply
ECAMScript 3给Function 的原型定义了两个方法,它们是Function.prototype.call
和Function.prototype.apply
。在实际开发中,特别是在一些函数式风格的代码编写中,call 和apply 方法尤为有用。在JavaScript 版本的设计模式中,这两个方法的应用也非常广泛,能熟练运用这两个方法,是我们真正成为一名JavaScript 程序员的重要一步。
call和apply的区别
Function.prototype.call
和Function.prototype.apply
都是非常常用的方法。它们的作用一模一样,区别仅在于传入参数形式的不同。
apply 接受两个参数,第一个参数指定了函数体内this 对象的指向,第二个参数为一个带下标的集合,这个集合可以为数组,也可以为类数组,apply 方法把这个集合中的元素作为参数传递给被调用的函数:
var func = function( a, b, c ){
alert ( [ a, b, c ] ); // 输出 [ 1, 2, 3 ]
};
func.apply( null, [ 1, 2, 3 ] );
//在这段代码中,参数 1、2、3 被放在数组中一起传入func 函数,它们分别对应func 参数列表中的a、b、c。
call 传入的参数数量不固定,跟apply 相同的是,第一个参数也是代表函数体内的this 指向,从第二个参数开始往后,每个参数被依次传入函数:
var func = function( a, b, c ){
alert ( [ a, b, c ] ); // 输出 [ 1, 2, 3 ]
};
func.call( null, 1, 2, 3 );
当调用一个函数时,JavaScript 的解释器并不会计较形参和实参在数量、类型以及顺序上的区别,JavaScript的参数在内部就是用一个数组来表示的。
从这个意义上说,apply 比call 的使用率更高,我们不必关心具体有多少参数被传入函数,只要用apply 一股脑地推过去就可以了。
call 是包装在apply上面的一颗语法糖,如果我们明确地知道函数接受多少个参数,而且想一目了然地表达形参和实参的对应关系,那么也可以用call 来传送参数。
当使用call 或者apply 的时候,如果我们传入的第一个参数为null,函数体内的this 会指向默认的宿主对象,在浏览器中则是window:
var func = function( a, b, c ){
alert ( this === window ); // 输出true
};
func.apply( null, [ 1, 2, 3 ] );
//但如果是在严格模式下,函数体内的this 还是为null:
var func = function( a, b, c ){
"use strict";
alert ( this === null ); // 输出true
}
func.apply( null, [ 1, 2, 3 ] );
借用其他对象的方法
有时候我们使用call 或者apply 的目的不在于指定this 指向,而是另有用途,比如借用其他对象的方法。那么我们可以传入null 来代替某个具体的对象:
Math.max.apply( null, [ 1, 2, 5, 3, 4 ] ) // 输出:5