Js中caller和callee的区别

JavaScript010

Js中caller和callee的区别,第1张

首先,每个函数都有一个arguments对象(即通常所说的参数对象,这个对象只在函数内部可用),它引用了传递给这个函数的参数。而callee是arguments对象的一个属性,引用的是arguments对象代表的参数所在的函数。假设有一个函数 function f(a,b,c),则arguments是对参数a,b,c的引用,arguments.callee是函数f(是参数a,b,c所在的函数)。

caller是什么呢?caller是函数的一个属性,引用了调用本函数的父函数,如果是顶层调用(即没有父函数),则返回null。假设有两个函数f1和f2,且在f1中调用了f2,则f2.caller就是f1。也就是说caller是对调用本函数的父函数的引用。

最后总结一下:

caller返回一个函数(父函数)的引用,这个函数调用了当前的函数callee返回正在执行的函数本身的引用,而它是arguments对象的一个属性。

还有,使用caller时要注意:

1 这个属性只有当函数在执行时才有用,

2 如果函数是由顶层调用的,则caller返回null。

早起版本的 JavaScript 没有具名函数表达式(named function expression),所以在函数表达式里么没有办法实现递归。

比如下面实现阶乘的函数:

function factorial ( n ) {

    return !( n > 1 ) ? 1 : factorial( n - 1 ) * n}[1,2,3,4,5].map(factorial)

如果写成函数表达式的话:

[1,2,3,4,5].map( function( n ) {

    // 这里要怎样递归?

} )

所以添加了 arguments.callee 来实现对执行函数本身的调用:

[1,2,3,4,5].map( function( n ) {

    return !( n > 1 ) ? 1 : arguments.callee( n - 1 ) * n

} )

但是现在的JavaScript 支持了具名函数表达式:

[ 1, 2, 3, 4, 5 ].map( function factorial( n ) {

    return !( n > 1 ) ? 1 : factorial( n - 1 ) * n

} )

这样写有以下的好处:

可以像正常一样调用函数

不会在函数外面的作用域创建变量(IE8或者更早的浏览器还是会)

比起用 arguments 对象来说,性能更加优秀

同时,使用 arguments.callee 还会带来函数引用优化问题和尾递归优化的问题。

以上部分内容资料来自:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode

http://stackoverflow.com/questions/103598/why-was-the-arguments-callee-caller-property-deprecated-in-javascript