4.2.3 Function
函数是一种特殊的数据类型,它实际上是一种对象。
4.2.3.3 call( )和apply( )
1.在JavaScript中,每个函数都有call()和apply()两个方法。
这两个方法的两个功能:
(1)用他们来触发函数,并指定相关的调用参数。
(2)他可以让一个对象去“借用“另一个对象的方法,并为已所用。这也是非常简单而实用的代码重用。
2.通过一个例子来讲解call
(1)定义一个some_obj对象,该对象有一个say()方法:
var some_obj={
name: ‘peichunyan‘,
say: function(who){
return ‘Haya‘ + who + ‘, I am ‘ + this.name;
}
};
这样,就可以调用该对象的say( )方法了,并在其中使用this.name来访问其name属性了:some_obj.say( ‘Kitty‘); //输出:Haya Kitty, I am peichunyan
(2)下面,我们再创建一个my_obj对象,它只有一个name属性:var my_obj={ name: ‘LiYundi‘};
(3)对于my_obj,也想拥有和some_obj的say( )方法相同功能的方法,因此,我们希望将该方法当做my_obj自身的方法来调用(没必要自己再重复实现一遍)。在这样情况下,我们就可以试试say( )函数中的对象方法call( ):
some_obj.say.call(my_obj, ‘Yanglan‘);
//输出: "Haya Yanglan, I am LiYundi "
(4)解释:由于我们在调用say( )函数的对象方法call时传递了两个参数:对象my_obj和字符串"Yanglan”.这样一来,当say( )被调用时,其中的this就被自动设置成了my_obj对象的引用。因此我们看到,this.name返回的不再是“peichunyan”,而是“LiYundi”了。
(5)如果我们调用call方法时,需要传递更多的参数,可以在后面依次加入它们:some_obj.someMethod.call(my_obj, ‘a‘, ‘b‘, ‘c‘);
- apply( )
apply( )的工作方式与call( )基本相同,唯一的不同之处在于参数的传递形式,这里目标函数所需要的参数都是通过一个数组来传递。所以,下面两行代码的作用是等效的:
some_obj.someMethod.call(my_obj, ‘a‘, ‘b‘, ‘c‘);
some_obj.someMethod.apply(my_obj, [‘a‘, ‘b‘, ‘c‘]);
所以,对于之前的示例,也可以这样写:
some_obj.say.apply(my_obj, [ ‘Yanglan‘]);
//输出: "Haya Yanglan, I am LiYundi "
4.2.3.4重新认识arguments对象
1.可以在一个函数中通过arguments来访问传递给该函数所需的全部参数。栗子:
function f( ){
return arguments;
}
f(1,2,3); //[1,2,3]
2.尽管arguments看上去像是一个数组,但它实际上是一个类似数组的对象。它和数组相似是因为其中也包含了索引元素和length属性。但相似之处也就到此为止了,因为arguments不提供一些像sort()、slice()这样的数组方法。
- 但我们可以把arguments转换成数组,这样就可以对它使用各种各样的数组方法了。
例子:
function f( ){
var args = [].slice.call( arguments);
return args.reverse( );
}
f(1,2,3,4); //[4,3,2,1]
这里的做法是:新建一个空数组,再使用它的slice属性。也可以用Array.prototype.slice来调用同一个函数。
4.2.3.5 推断对象类型
(1)问题:既然数组的typeof返回值也是“object”,那么要如何区分对象和数组呢?
(2)答案:使用Object对象的toString()方法。这个方法会返回所创建对象的内部类名。
(3)例:
Object.prototype.toString.call( { } ); // [object Object]
Object.prototype.toString.call( [ ] ); // [object Array]
在这里,toString()方法必须要来自于Object构造器的prototype属性。直接调用Array的toString()方法是不行的,因为在Array对象里,这个方法已经出于其它目的被重写了。[1, 2, 3].toString( );