js在参数中命名了函数,不能访问出函数

js named function in parameter, can not access out of function

本文关键字:函数 不能 访问 参数 js      更新时间:2023-09-26
参数中的js命名函数,不能访问函数外的

因为ECMAScript的第5版禁止在严格模式下使用arguments.callele()。

mdn警告

所以我决定不使用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是未定义的?

jsfiddle演示

您实际上在问两个问题。第一个很简单:

[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规范,第13.2.1节明确指出,创建的新执行上下文包含实际参数(参数列表)。也就是说,a是在d的执行上下文中定义的,而不是在调用者中定义的。看起来IE在表达错误的行为。

函数表达式的名称在其定义的命名空间中不引用自己(IE错误),但在其自身中引用自己

[1].map(function foo() {return foo;});
// [function foo() {return foo;}]
foo;
// undefined

如果您想要对函数的引用,以便它可以被重复使用,请创建对它的引用,或者返回编写功能声明作为一个语句),或者将的函数表达式设置为一个变量,并根据需要传递该变量

var bar = function foo() {return foo;};
[1].map(bar);
// [function foo() {return foo;}]
foo;
// undefined
bar;
// function foo() {return foo;}

请注意,在本例中名为foo函数中,除非稍后再次更改bar,否则foobar都将指向同一功能

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

你说你前面的例子不起作用,但我不得不不同意你的观点,

[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);
});