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 函数。
浙公网安备 33010602011771号