首页 > 技术文章 > JavaScript中call方法的使用

JavaScript中call方法的使用

2010年1月15日 20:02 by webphoenix

  今天在看Mootools JavaScript Framework时,看到了N个地方都调用了call这个方法,虽然知道call是JS里内置的,但是由于平常很少用到,几乎不了解它的功能。今天google一下,这个call功能的确很强,出乎我的意料。现把学到的知识分享一下,介绍call的同时也同时说下其他几个相关的方法和属性 callee,caller,apply。

1.call方法

  微软的JScript帮助文档里这么说的:

call 方法
调用一个对象的一个方法,以另一个对象替换当前对象。

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 方法
应用某一对象的一个方法,用另一个对象替换当前对象。
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的用法,希望有点帮助

技术文章 ,

  1. 目前还没有任何评论.
  1. 目前还没有任何 trackbacks 和 pingbacks.
您必须在 登录 后才能发布评论.