叶落为重生每片落下的叶子都是为了下一次的涅槃...^_^

关于arguments,caller以及匿名函数调用的问题

  此文内容不深,就当一个简单的笔记或总结吧。

  先从arguments对象说起吧,[fnName.]arguments (其中fnName可选),为当前执行的 function 对象返回一个arguments 对象。

  它有几个特性:

  1.arguments是进行函数调用时,除了指定的参数外,还另外创建的一个隐藏对象。

  2.arguments 对象只有函数开始时才可用。

  3.arguments是一个类似数组但不是数组的对象,说它类似数组是因为其具有数组一样的访问性质及方式,可以由arguments[n]来访问对应的单个参数的值,并拥有数组长度属性length。

  4.还有就是arguments对象存储的是实际传递给函数的参数,而非函数声明所定义的参数列表

  5.不能显式创建 arguments 对象。

下面就3,4两点举两个简单的例子:

function testArg(a,b){
	alert(arguments.length);//实际参数个数 
	alert(testArg.length); //声明参数个数
	arguments.length != 0&&alert(arguments[0]); //可以通过类似Array的方式访问arguments内部元素
}

 

您可以尝试运行下面的测试:
testArg()
当我们传一个参数时: testArg(true)

正因为上面的原因,所以我们说它是类似于Array的对象,但是它确实又不是Array对象。

 

//arguments类似Array,但又不是Array
Array.prototype.self = "me!"
alert((new Array()).self); //me!
(function(){
	alert(arguments.self); //undefined
})();

同样,也可以用instanceof来判断:

(function(){
        alert(arguments instanceof Object); //true 
	alert(arguments instanceof Array); //false
})()

 

 

  下面说说caller,它是用于返回对一个函数的“引用”,表明函数调用了该函数,它有以下几个特性:

  1.caller 属性只有在函数执行时才有定义。

  2.如果函数是由顶层调用的,那么 caller 包含的就是 null 。

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

 

/* == caller ==*/
function testCaller(){ //fnName.caller
	if(testCaller.caller){
		alert(testCaller.caller);
	}
	else {alert('top function')}
}

在函数上下文中调用看看:(function(){testCaller()})()

可以看到,结果为调用testCaller()的函数,也就是外层匿名函数的反编译文本。

 

恩,下面接着说arguments的另一个属性callee,(貌似叙述顺序有点乱,不好意思),说callee之前,咱们还是先说说匿名函数。

 

function fn1(){alert('one')}
var fn1 = function(){alert('one')}

这两种方式有什么区别?

 

1 第一种方式定义函数,函数声明过程在整个程序执行之前的预处理就完成了,所以只要处于同一个作用域,就可以访问到,即使在定义之前调用它也可以。

2 第二种方式通过匿名函数创建,这种方式函数只能按照程序流程执行到定义的那一行代码才被声明,所以只能在定义之后调用它。

大家也看到了,上面举的几个小例子里就用了匿名函数。

现在问题出来了,我们知道,函数是可以递归调用的,比如我们做个高斯很小就会的题目:1+2+3+...+99+100?

这个问题就可以用递归做:

 

function sum(n){
	return n>0?n+sum(n-1):n;
}
alert(sum(100));

大家可以看下结果是不是当前高斯算出来的5050. run

那如果是匿名函数的递归调用呢?这是就需要刚刚提到的callee属性了。回到callee上来

callee 属性的初始值就是正被执行的 Function 对象,它返回的是当前正在执行的函数正文。

callee 属性是 arguments 对象的一个成员,它表示对函数对象本身的引用,这有利于匿名函数的递归或者保证函数的封装性。

下面就借助callee用匿名函数改写上面的简单例子:

 

(function(n){
    return n>0?n+arguments.callee(n-1):n
})(100);

这种方式是不是要优雅的多,而且比起直接用函数名作递归调用,这种方式更好的体现了是在调用自身。

 

恩,此文差不多就到这儿吧...

posted on 2010-10-08 14:04  岑安  阅读(1705)  评论(0编辑  收藏  举报

导航