为什么参数。被呼叫者。呼叫者财产的使用JavaScript?
-
01-07-2019 - |
题
为什么 arguments.callee.caller
酒店使用JavaScript?
它的加入,然后使用JavaScript,但它是完全省的写法。一些浏览器(Mozilla,即)一直支持它,并没有任何计划在地图上除去支持。其他人(野生动物园,歌剧院)通过了对它的支持,但支持关于老年浏览器是不可靠的。
是有一个很好的理由把这一宝贵的功能在地狱?
(或者,是否有更好的方式来抓住一个把手在叫?)
解决方案
早期版本的JavaScript不允许名功能的表达,因为我们不能让递归功能的表达:
// This snippet will work:
function factorial(n) {
return (!(n>1))? 1 : factorial(n-1)*n;
}
[1,2,3,4,5].map(factorial);
// But this snippet will not:
[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();
无论如何,写3个解决这些问题通过允许名功能的表达,例如:
[1,2,3,4,5].map(function factorial(n) {
return (!(n>1))? 1 : factorial(n-1)*n;
});
这有许多好处:
在功能上可以称之为如同任何其他内部编码。
它不污染的名字空间。
值
this
不会改变。这是更高性能的(访问 争论的对象 是昂贵)。
哎呦,
只是意识到,除了一切问题是有关 arguments.callee.caller
, 或者更具体地说 Function.caller
.
在任何时间点上你可以找到的最深切的呼叫者的任何功能上的堆,并且如我上面所说的,看的话堆有一个单一的主要影响:它使大量的优化不可能的,或者更多困难。
例如。如果我们不能保证一个功能 f
不会叫一个未知的功能,那是不可能的内联 f
.基本上,这意味着任何电话网站可能已经被平凡可内联积累了大量的警卫、采取:
function f(a, b, c, d, e) { return a ? b * c : d * e; }
如果js解释不能保证提供的所有参数编号在呼叫的是,它需要插入检查所有的参数之内联的代码,或者它不能行内的功能。
现在,在这种特定情况下,能解释应该能够重新安排检查将更加优化和不检查任何价值将不能使用。然而在许多情况下,是不可能的,因此它变得不可能的内联。
其他提示
arguments.callee.call呃
是 不 弃用的,虽然它不会使用的 Function.call呃
财产。(arguments.callee
只会给你一个参考的当前功能)
Function.call呃
, 虽然非标准根据ECMA3,是实现全 目前所有主要的浏览器.arguments.call呃
是 弃赞成Function.call呃
, ,而不是实现某些目前主要的浏览器(例如Firefox3).
因此情况是不理想,但是如果你想要访问的调功能在Javascript在所有主要的浏览器,可以使用 Function.call呃
财产,无论是直接访问一个名叫功能基准,或从一个匿名的功能通过 arguments.callee
财产。
只是一个扩展。 “this”的值递归期间的变化。在以下(修改)示例中,factorial获取{foo:true}对象。
[1,2,3,4,5].map(function factorial(n) {
console.log(this);
return (!(n>1))? 1 : factorial(n-1)*n;
}, {foo:true} );
第一次调用的factorial获取对象,但对于递归调用则不然。