js在参数中命名函数,无法访问函数
因为第5版ECMAScript禁止在严格模式下使用arguments.callee()。
所以我决定不使用callee
,而是使用命名函数
mdn
中的示例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 factorial(n) {
return !(n > 1) ? 1 : /* what goes here? */ factorial(n - 1) * n;
});
这是一个好主意,但我想重用函数factorial
样本
function d(x){return x;}
d(function a(){});
d(a);// this is not work, a is undefined(works in ie, failed in ff and chrome)
这让我感到困扰,正如我所知,js中的范围是功能级别,为什么第二个a未定义?
答案 0 :(得分:2)
你真的在这里问两个问题。第一个很简单:
[1,2,3,4,5].map(function factorial(n) {
return !(n > 1) ? 1 : /* what goes here? */ factorial(n - 1) * n;
});
你在那里工作得很好。换句话说,由于您正在命名函数(factorial),因此该函数体内可以使用该标识符,从而实现递归。
你的第二个问题有点棘手:
function d(x){return x;}
d(function a(){});
d(a);// this is not work, a is undefined(works in ie, failed in ff and chrome)
a
未定义是正确的。如果您阅读ECMAScript specification,则第13.2.1节明确指出创建的新执行上下文包含实际参数(参数列表)。也就是说,a
是在d
的执行上下文中定义的,而不是调用者。看起来IE似乎表达了错误的行为。
答案 1 :(得分:1)
函数表达式的名称不会在它定义的命名空间中引用自身(IE中的错误),但它本身就引用了它自己
[1].map(function foo() {return foo;});
// [function foo() {return foo;}]
foo;
// undefined
如果您想要引用函数以便可以重复使用它,请创建对它的引用,或者返回编写函数声明( > function as a statement),或将函数表达式设置为变量,并根据需要传递变量
var bar = function foo() {return foo;};
[1].map(bar);
// [function foo() {return foo;}]
foo;
// undefined
bar;
// function foo() {return foo;}
请注意,在此示例中名为foo
的函数中,foo
和bar
都将指向相同的函数 ,除非稍后再次更改bar
。
var bar = function foo() {return foo === bar;};
bar(); // true, bar is foo inside the function
// change value of bar, keep a reference to function foo
var temp = bar;
bar = 'something else';
temp(); // false, bar is no longer foo inside the function
答案 2 :(得分:0)
你说你之前的例子不起作用,但我不得不反对你,
[1,2,3,4,5].map(function factorial(n) {
return n == 0 ? 1 : factorial(n - 1) * n;
});
我尝试了这个(是的,我修改了一下)使用基本日志记录,并且每次递归都记录了n-1,表明递归工作正常。我相信保罗解释得很好。
无论如何,我建议改变你在这里思考的方式,因为想象一下你是否找到了阶乘(100)。你一直在做
... * factorial(98 - 1) * 98 * 99 * 100
想象一下过载。我建议添加一个可选参数,它是当前评估的阶乘的总和,你的结果是相同的,但过载要少一些。
[1,2,3,4,5].map(function factorial(n, sum) {
var sum = sum || 1;
return n == 0 ? 1 : factorial(n - 1, sum*n);
});