悟透前端 | 参悟 Javascript 中的 call 和 apply
对于前端工程师来说,
call
、apply
算是常用的函数方法,允许通过函数和在函数调用中指定this
的指向。那么这两个方法到底有什么区别呢?本文将详细介绍这两个方法,顺便加深对其理解。
call
方法使用一个指定的 this
值和单独给出的一个或多个参数来调用一个函数。允许为不同的对象分配和调用属于一个对象的函数/方法。提供新的 this 值给当前调用的函数/方法。你可以使用 call
来实现继承:写一个方法,然后让另外一个新的对象来继承它(而不是在新对象中再写一次这个方法)。
语法
thisArg
:可选的。
在 function
函数运行时使用的 this
值。请注意,this
可能不是该方法看到的实际值:如果这个函数处于非严格模式下,则指定为 null
或 undefined
时会自动替换为指向全局对象,原始值会被包装。
arg1, arg2, ...
:指定的参数列表。
返回值
使用调用者提供的 this
值和参数调用该函数的返回值。若该方法没有返回值,则返回 undefined
。
apply
apply()
方法调用一个具有给定this
值的函数,以及作为一个数组(或类似数组对象)提供的参数。在调用一个存在的函数时,你可以为其指定一个 this
对象。 this
指当前对象,也就是正在调用这个函数的对象。 使用 apply
, 可以只写一次这个方法然后在另一个对象中继承它,而不用在新对象中重复写该方法。
语法
thisArg
:必选的。
在 func
函数运行时使用的 this
值。请注意,this
可能不是该方法看到的实际值:如果这个函数处于非严格模式下,则指定为 null
或 undefined
时会自动替换为指向全局对象,原始值会被包装。
argsArray
:可选的。
一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 func
函数。如果该参数的值为 null
或 undefined
,则表示不需要传入任何参数。从 ECMAScript 5 开始可以使用类数组对象。 浏览器兼容性 请参阅本文底部内容。
返回值
调用有指定this
值和参数的函数的结果。
call 和 apply 的区别
它们的作用一模一样,区别仅在于传入参数形式的不同。
apply
接受两个参数,第一个参数指定了函数体内 this
对象的指向,第二个参数为一个带下标的集合,这个集合可以为数组,也可以为类数组,apply
方法把这个集合中的元素作为参数传递给调用的函数:
这段代码中,参数 1、2、3 被放在数组中一起传入 func
函数,它们分别对应 func
参数列表中的 a 、b 、c
。
call
传入的参数数量不固定,跟 apply
相同的是,第一个参数也是代表函数体内的 this
指向,从第二个参数开始往后,每个参数被依次传入函数:
调用一个函数时,Javascript 的解释器并不会计较形参和实参在数量、类型以及顺序上的区别,Javascript 的参数在内部就是用一个数组来表示的。
从这个意义上说,apply
比 call
的使用率更高,不关心具体多少参数被传入函数,只要用 apply
一股脑地推过去就可以了。
call
是包装在 apply
上的一颗语法糖,如果明确地知道函数接收多少个参数,而且想一目了然地表达形参和实参的对应关系,那么可以用 call
来传送参数。
当使用 call
或者 apply
的时候,如果传入的第一个参数为 null
,函数体内的 this
会指向默认的宿主对象,在浏览器中则是 window
:
如果是在严格模式下,函数体内的 this
还是为 null :
改变 this 指向
call
方法的第一个参数是作为函数上下文的对象,上面的代码把 obj
作为参数传给了 func
,此时函数里的 this
便指向了 obj
对象。此处 func
函数相当于下面的方法:
apply()方法的一些妙用
Math.max
可以实现得到数组中最大的一项
因为Math.max
不支持Math.max([param1,param2])
也就是数组,但是它支持Math.max(param1,param2...)
,所以可以根据apply
的特点来解决 var max=Math.max.apply(null,array)
,这样就轻易的可以得到一个数组中的最大项(apply
会将一个数组转换为一个参数接一个参数的方式传递给方法)这块在调用的时候第一个参数给了null
,这是因为没有对象去调用这个方法,我只需要用这个方法帮我运算,得到返回的结果就行,所以直接传递了一个null
过去。
用这种方法也可以实现得到数组中的最小项:Math.min.apply(null,array)
Array.prototype.push
实现两个数组的合并
同样push
方法没有提供push
一个数组,但是它提供了push(param1,param2...paramN)
,同样也可以用apply
来转换一下这个数组,即:
版权声明: 本文为 InfoQ 作者【devpoint】的原创文章。
原文链接:【http://xie.infoq.cn/article/02e3a75c0f825a598281226f7】。文章转载请联系作者。
评论