(Javascript)为什么废弃caller和callee

Apr 6th, 2011 Anything

  早期的Javascript不允许给函数表达式命名,因此你无法直接用函数表达式来写递归,例如一个阶乘函数:

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) { return (!(n>1))? 1 : /* what goes here? */ (n-1)*n; });

  所以就需要 arguments.callee 了:

[1,2,3,4,5].map(function(n) { return (!(n>1))? 1 : arguments.callee(n-1)*n; });

  但是这个解决方案并不好,在这种方式下用函数表达式实现尾递归十分困难,另一个主要问题是这样的递归调用会产生新的 this 引用:

var global = this; var sillyFunction = function (recursed) { if (!recursed) return arguments.callee(true); if (this !== global) alert("This is: " + this); else alert("This is the global"); } sillyFunction();

  因此,ECMAScript3允许为函数表达式指定名字,以解决此问题:

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

  这样做有如下好处:
  1、函数的调用方式更直观
  2、不污染命名空间
  3、this 的值保持不变
  4、性能更好(访问 arguments 变量的消耗是很高的)

参考资料:
http://stackoverflow.com/questions/103598/why-was-the-arguments-callee-caller-property-deprecated-in-javascript
https://developer.mozilla.org/en/JavaScript/Reference/functions_and_function_scope/arguments
http://en.wikipedia.org/wiki/JavaScript

Leave a Reply