ECMAScript 中的call、apply、arguments、caller和callee的学习

一、call和apply 的作用 -- 对象冒充

先看一段示例代码

var Animal = function(name) {
this.name = name;
this.sayName = function() {
alert("My name is " + this.name);
}
}

var Dog = function(name, age) {
Animal.call(this, name);
}

var wangcai = new Dog("wangcai");
wangcai.sayName(); //out print string "My name is wangcai"

Animal构造函数使用 this 关键字给所有属性和方法赋值(即采用类声明的构造函数方式)。因为构造函数只是一个函数,所以可使 Animal 构造函数成为 Dog 的方法,即Dog中调用Animal.call(this, name)。Dog 就会收到 Animal 的构造函数中定义的属性和方法。

简单来说,就是创建Dog的实例时,调用Animal.call 在Dog的this添加上了name属性和sayName方法,Dog就继承Animal的属性和方法。

apply 与 call的功能是一样的,把上面的代码修改为Animal.apply(this, [name])和Animal.call(this, name) 是等同的,不难理解,apply第二个参数接受一个数组或者arguments(类似于数组,接下来会介绍)

二、关于arguments -- 调用该函数的参数

看一段示例代码

var Animal = function(name) {
this.name = name;
this.sayName = function() {
alert("My name is " + this.name);
}
}

var Dog = function(name, age) {
alert("arguments:" + arguments + ", arguments length:" + arguments.length);
alert(arguments instanceof Array);
alert(arguments instanceof Object);
Animal.apply(this, [name]);
}

var wangcai = new Dog("wangcai");
//out print string "arguments:[object Arguments], arguments length:1"
//
out print string false;
//
out print string true;

arguments是进行函数调用时,创建的一个隐藏对象。arguments是一个类似数组但不是数组的对象,说它类似数组是因为其具有数组一样的访问性质及方式,可以由arguments[n]来访问对应的单个参数的值,并拥有数组长度属性length。还有就是arguments对象存储的是实际传递给函数的参数,而不局限于函数声明所定义的参数列表,而且不能显式创建 arguments 对象。arguments 对象只有函数执行时才可用。

有了arguments,我们就可以模拟出类似于Java中的重载

Animal.apply(this, name) 也可以修改为Animal.apply(this, arguments)了。

三、caller 属性 -- 函数调用了当前函数

先看一段代码

var callerEx = function() {
if(callerEx.caller) {
alert(callerEx.caller.toString());
} else {
alert("你是直接调用该方法的");
}
}

var callerExExe = function(arg1, arg2) {
callerEx();
}

callerExExe();
callerEx();

//out print string function (arg1, arg2) {callerEx();}
//
out print string "你是直接调用该方法的"

对于函数来说,caller 属性只有在函数执行时才有定义。 如果函数是由 JScript 程序的顶层调用的,那么 caller 包含的就是 null 。

如果在字符串上下文中使用 caller 属性,那么结果和 functionName.toString 一样,也就是说,显示的是函数的反编译文本。

三、callee 属性 

看一段代码示例

function factorial(n){
if (n <= 0) {
return 1;
} else {
return n * factorial(n - 1);
}
}
alert(factorial(3)); //out print number 6

function factorial(n){
if (n <= 0) {
return 1;
} else {
return n * arguments.callee(n - 1);
}
}
alert(factorial(3)); //out print number 6

上面两个factorial 函数,计算阶层功能函数,使用到递归功能,不同的时后者使用arguments对象上的callee属性,callee 属性是 arguments 对象的一个成员,仅当相关函数正在执行时才可用。callee 属性的初始值就是正被执行的 Function 对象。这允许匿名的递归函数。

理解了call,apply,arguments,caller,callee,就不难理解Flex 和 EXT 或者 YUI中常用到的Delegate 函数。



 



posted @ 2012-01-07 16:21  script9  阅读(257)  评论(0)    收藏  举报