本文深入解析JavaScript中apply和call方法的核心作用,即改变函数执行时的this指向。详细对比两者在参数传递方式上的差异:call接受离散参数,apply接收数组。通过对象方法借用、类数组转数组等实际案例,展示如何利用这两个方法实现动态上下文绑定和代码复用。
apply与call的核心作用
call和apply方法的主要目的是改变函数运行时的上下文环境,也就是修改函数内部this关键字的指向。这一机制的存在,源于JavaScript中函数拥有定义时的上下文和运行时的上下文,且运行时上下文是可以被动态改变的。
回到目录定义
fun.apply(thisArg, [argsArray])
fun.call(thisArg, arg1,arg2, ...)
这里的thisArg参数允许传入null或undefined,若传入此类值,则默认指向全局对象。关于更详细的规范说明,可参考MDN文档中关于apply()和call()的章节。
参数传递方式的差异
这两个方法的功能完全一致,区别仅在于接收参数的形式不同。假设存在如下定义的函数:
var func1 = function(arg1, arg2){};
调用方式可以是func1.call(this, arg1, arg2),也可以是func1.apply(this, [arg1, arg2])。其中的this代表希望绑定的上下文对象,它可以是任意JavaScript对象(因为JS中一切皆对象)。call方法要求将参数逐个列出,而apply方法则要求将参数封装在一个数组中。
由于JavaScript函数的参数数量是不固定的,当参数数量明确已知时,推荐使用call方法;当参数数量不确定时,则使用apply方法,并将参数推入数组后再传递。如果函数内部需要处理不确定的参数数量,可以通过arguments数组来遍历所有传入的参数。
动态改变this指向的应用
回到目录一个例子
在JavaScript面向对象编程中,我们通常这样定义构造函数:
funciton programmer() {
}
programmer.prototype = {
hobby: 'programming',
say.function() {
alert('I love' + this.hobby);
}
}
var xiaoMing = new programmer();
xiaoMing.say();
假设现在有一个设计妹子对象xiaoHua = {hobby: 'designing'},如果我们不想为它重新定义say方法,就可以通过call或apply来借用xiaoMin的say方法,例如执行xiaoMing.say.call(xiaoHua)。
由此可见,call和apply的出现是为了动态改变this的指向。当某个对象缺少某个方法或属性,而另一个对象拥有该方法时,就可以借助call或apply来调用其他对象的方法进行操作。
obj.call(thisObj, arg1, arg2, ...);
obj.apply(thisObj, [arg1, arg2, ...]);
这两个方法的作用是将obj(即this)绑定到thisObj上,此时thisObj就具备了(或继承了)obj的属性和方法。
类数组转数组的实战技巧
一个常见的应用场景是,通过document.getElementByTagName选择的节点属于类数组对象,它无法直接使用Array原型下的push、pop等方法。但我们可以利用以下方式:
var domNodes = Array.prototype.slice.call(document.getElementsByTagName("*"));
使用Array.prototype.slice.call可以将所有具有length属性的对象转换为真正的数组,这样domNodes就可以使用Array下的所有方法了。
以上这篇彻底搞懂JavaScript中的apply和call方法(必看)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持本站。