call( )与apply( )

102 阅读2分钟

在 JavaScript 中,每个函数都有 call( ) 和 apply( ) 两个方法,你可以用它们来触发函数,并指定相关的调用参数。

此外,这两个方法还有另外一个功能,它可以让一个对象去“借用”另一个对象的方法,并为已所用。这也是一种非常简单而实用的代码重用。

下面我们定义一个 some_obj 对象,该对象中有一个 say( ) 方法:

var some_obj = {
    name:'Ninja',
    say:function(who){
        return 'Haya ' + who + ', I am a ' + this.name;
    }
};

这样一来,我们就可以调用该对象的 say( ) 方法,并在其中使用 this.name 来访问其 name 属性了:

some_obj.say('Dude');    //"Haya Dude, I am a Ninja"

下面,我们再创建一个 my_obj 对象,它只有一个 name 属性:

var my_obj = {name:'Scripting guru'};

显然,some_obj 的 say( ) 方法也适用于 my_obj,因此我们希望将该方法当作 my_obj 自身的方法来调用。在这种情况下,我们就可以试试 say( ) 函数中的对象方法 call( ) :

some_obj.say.call(my_obj,'Asde');    //"Haya Asde, I am a Scripting guru"

成功了!但你明白这是怎么回事吗?由于我们在调用 say( ) 函数的对象方法 call( ) 时传递了两个参数:对象 my_obj 和字符串 'Asde' 。这样一来,当 say( ) 被调用时,其中的 this 就被自动设置成了 my_obj 对象的引用。因此我们看到,this.name 返回的不再是 'Ninja' ,而是 'Scripting guru' 了。

如果我们调用 call 方法时需要传递更多的参数,可以在后面依次加入它们:

some_obj.someMethod.call(my_obj, 'a','b','c');

另外,如果我们没有将对象传递给 call( ) 的首参数,或者传递给它的是 null,它的调用对象将会被默认为全局对象。

apply( ) 的工作方式与 call( ) 基本相同,唯一不同之处在于参数的传递形式,这里目标函数所需要的参数都是通过一个数组来传递。所以,下面两行代码的作用是等效的:

some_obj.say.apply(my_obj,['A','B','C']);
some_obj.say.call(my_obj,'A','B','C');

因而,对于之前的示例,我们也可以这样写:

some_obj.say.apply(my_obj,['Asde']);    //"Haya Asde, I am a Scripting guru"

本文摘自《JavaScript面向对象编程指南》,分享的目的仅供个人学习和理解,如需转载请备注本文出处,谢谢!