JavaScript中call方法的使用
今天在看Mootools JavaScript Framework时,看到了N个地方都调用了call这个方法,虽然知道call是JS里内置的,但是由于平常很少用到,几乎不了解它的功能。今天google一下,这个call功能的确很强,出乎我的意料。现把学到的知识分享一下,介绍call的同时也同时说下其他几个相关的方法和属性 callee,caller,apply。
1.call方法
微软的JScript帮助文档里这么说的:
调用一个对象的一个方法,以另一个对象替换当前对象。
call([thisObj[,arg1[, arg2[, [,.argN]]]]])
参数
thisObj 可选项。将被用作当前对象的对象。
arg1, arg2, , argN 可选项。将被传递方法参数序列。
说明
call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。
如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。
要求
版本 5.5
请参阅
应用于:Function 对象
刚开始看到了“调用一个对象的一个方法,以另一个对象替换当前对象”这句话时,我就傻了,实在没搞懂,谁调用谁替换谁啊。看到后面,也没一个例子,后来还是google一下,终于找到了一篇【javaScript 中 call 函数的用法说明】,这篇文章里说的还是蛮清楚的,我在这基础上“提炼”扩展了一下
1.1:只有方法才call方法,其他对象或属性没有
这里指的方法即typeof(any)==’function’,其他typeof非function的都没有call方法
//如方法funcA
function funcA()
{
//codes
}
//对象objB
var objB = {
/* property */
};
var strC = "12345";
//那么只有 funcA有call方法,objB, strC都没有call方法
请看执行下面这段代码
var Natives = [
['String',String],
['Math',Math],
['Object',Object],
['Array',Array],
['Date',Date],
['Number',Number],
['RegExp',RegExp],
['Boolean',Boolean],
['Error',Error]
];
var str = [];
for(var i=0,length=Natives.length;i<length;i++)
{
var str = 'typeof('+Natives[i][0]+')=';
str += typeof(Natives[i][1])+',ttypeof(';
str += Natives[i][0]+'.call)=';
str += typeof(Natives[i][1].call);
str.push(str);
}
alert(str.join('n'));
1.2.call的使用
[object1.]func1.call(object2,arg1,arg2…);
举例如下
//例1
function Add(a,b) {
alert(a+b);
}
function Sub(a,b) {
alert(a-b);
}
Add.call(Sub,1,2);
//结果是弹出 3
Add.call(null,1,2);
//结果同样是弹出 3
//例2
function Class1() {
this.name = 'Class1';
this.show = function() {
alert('in class1, this.name='+this.name);
};
}
function Class2() {
this.name = 'Class2';
this.show = function() {
alert('in class2, this.name='+this.name);
};
}
var c1 = new Class1();
var c2 = new Class2();
c1.show.call(c2);
c1.show();
c2.show();
//c1.show.call(c2); 弹出 in class1,this.name=class2
//c2.show(); 弹出 in class2,this.name=class2
//
/*
这里有必要先解释一下为什么 c1.show.call(c2); 弹出的是 in class1,this.name=class2,
当你用c1.show call c2的时候就是调用 c1.show,不过c1.show中的this.name中的this,已经被Class2代替,此时的this.name就是Class2里的name即 'Class2',故弹出的是 in class1,this.name=class2
如果不明白,看下面这个例子
*/
//例3
function Class3() {
this.show = function() {
alert(this.name);
}
}
function Class4() {
this.name = 'Class4';
}
var c3 = new Class3();
var c4 = new Class4();
c3.show.call(c4);
/*
其实如果单看Class3,是有问题的,在show方法中却调用了一个 this.name,而Class3中根本就没有name没有这个属性
当执行c3.show.call(c4)时,把 Class3的show方法中的this用 Class4代替,此时的 this.name就是 Class4中的name 即 'Class4'
*/
下面说个继承的问题,JS中继承一般使用如下的方法
function Class5()
{
this.name = "Class5";
this.func2 = function(){
alert('this is function2,this.name='+this.name);
};
}
var C5 = new Class5();
function Class6()
{
this.name = "Class6";
this.func1 = function() {
alert('this is function1,this.name='+this.name);
}
}
Class6.prototype = C5;
var c6 = new Class6();
c6.func2();
//弹出 this is function2 ,this.name = Class6
这里的继承只能是单继承
下面看这个例子
function Class7()
{
this.name = 'Class7';
this.func2 = function(){
alert('this is func2,this name='+this.name);
}
}
function Class8()
{
Class7.call(this);
this.name = 'Class8';
}
var c8 = new Class8();
c8.func2();
//弹出 this is func2,this name=Class8
这种继承方式是不是感觉比上面那种要好一些?毕竟我直接用父“类”名去操作,而不需要实例化父类一个对象
还可以在 Class7.call(this)和this.name = ‘Class8′之间再去call其他的类,这样就做到了多继承,如下例
function ClassA()
{
this.valueA = 'valueA';
}
function ClassB()
{
this.vlaueB = 'valueB';
}
function ClassC()
{
ClassA.call(this);
ClassB.call(this);
this.test = function() {
alert(this.valueA+'+'+this.valueB);
}
}
var cCc = new ClassC()
cCc.test();
//弹出 valueA+valueB
2.apply 方法
微软的JScript参考文档里这样描述:
应用某一对象的一个方法,用另一个对象替换当前对象。
apply([thisObj[,argArray]])
参数
thisObj 可选项。将被用作当前对象的对象。
argArray 可选项。将被传递给该函数的参数数组。
说明
如果 argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一个 TypeError。
如果没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用作 thisObj, 并且无法被传递任何参数。
要求
版本 5.5
请参阅
应用于:Function 对象
和apply 方法和 call 类似,不过apply传的参数是通过一个数组而不是逐个传的
3. callee属性
callee属性是arguments的一个属性,返回方法的正文即
func.arguments.callee = func
如下面这个例子
function test()
{
alert(arguments.callee);
}
test();
//将弹出test方法的全部内容
还有这个
function factorial(n){
if (n <= 0)
return 1;
else
return n * arguments.callee(n - 1)
}
alert(factorial(3));
可以看出可以轻松实现递归调用
4.caller属性
caller属性是方法的一个属性,返回当前调用该方法的方法
即如果A方法调用了B方法,那么在B.caller即A
function A()
{
B();
}
function B()
{
alert(B.caller);
}
A();
以上简单的说了下 call、callee、caller和apply的用法,希望有点帮助
