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