我可以在这样的变量中创建一个递归函数:
/* Count down to 0 recursively.
*/
var functionHolder = function (counter) {
output(counter);
if (counter > 0) {
functionHolder(counter-1);
}
}这样,functionHolder(3);将输出3 2 1 0。假设我做了以下几件事:
var copyFunction = functionHolder;copyFunction(3);将输出如上所述的3 2 1 0。如果我随后将functionHolder更改如下:
functionHolder = function(whatever) {
output("Stop counting!");然后,functionHolder(3);会像预期的那样给出Stop counting!。
copyFunction(3);现在给出了3 Stop counting!,因为它引用了functionHolder,而不是它自己指向的函数。在某些情况下,这可能是可取的,但是是否有一种方法来编写函数,使其调用自身,而不是保存它的变量?
也就是说,是否可以只更改----行functionHolder(counter-1);,以便在调用copyFunction(3);时,通过所有这些步骤仍然会给3 2 1 0?我尝试了this(counter-1);,但这给了我错误this is not a function。
发布于 2011-08-15 12:56:58
使用命名函数表达式:
您可以给一个函数表达式一个名称,这个名称实际上是专用的,并且只能从函数的内部看到,如果是:
var factorial = function myself (n) {
if (n <= 1) {
return 1;
}
return n * myself(n-1);
}
typeof myself === 'undefined'在这里,myself只在函数本身中可见。
您可以使用这个私有名称递归地调用函数。
参见13. Function Definition的ECMAScript 5规范:
FunctionExpression中的标识符可以从FunctionExpression的FunctionBody中引用,从而允许函数递归地调用自己。但是,与FunctionDeclaration不同的是,FunctionExpression中的标识符不能被引用,也不影响包含FunctionExpression的作用域。
请注意,到第8版为止的Internet没有正确的行为,因为名称实际上在封闭的可变环境中是可见的,它引用了实际函数的副本(请参见下面patrick dw的注释)。
使用arguments.callee:
或者,您可以使用arguments.callee来引用当前函数:
var factorial = function (n) {
if (n <= 1) {
return 1;
}
return n * arguments.callee(n-1);
}然而,第5版的ECMAScript禁止在严格模式中使用arguments.callee():
(来自MDN):在正常代码中,arguments.callee指的是封闭函数。这个用例是弱的:简单地命名封装函数!此外,arguments.callee在很大程度上阻碍了像内联函数这样的优化,因为如果访问arguments.callee,必须使它能够提供对无内联函数的引用。用于严格模式函数的arguments.callee是一个不可删除的属性,它在设置或检索时抛出。
发布于 2015-09-29 18:24:11
您可以使用Y-组合器:(维基百科)
// ES5 syntax
var Y = function Y(a) {
return (function (a) {
return a(a);
})(function (b) {
return a(function (a) {
return b(b)(a);
});
});
};
// ES6 syntax
const Y = a=>(a=>a(a))(b=>a(a=>b(b)(a)));
// If the function accepts more than one parameter:
const Y = a=>(a=>a(a))(b=>a((...a)=>b(b)(...a)));你可以用它作为:
// ES5
var fn = Y(function(fn) {
return function(counter) {
console.log(counter);
if (counter > 0) {
fn(counter - 1);
}
}
});
// ES6
const fn = Y(fn => counter => {
console.log(counter);
if (counter > 0) {
fn(counter - 1);
}
});发布于 2015-05-29 23:36:43
我知道这是一个老问题,但我想提出一个解决方案,如果您想避免使用命名函数表达式,可以使用这个解决方案。(并不是说你应该或不应该回避它们,只是提出另一种解决方案)
var fn = (function() {
var innerFn = function(counter) {
console.log(counter);
if(counter > 0) {
innerFn(counter-1);
}
};
return innerFn;
})();
console.log("running fn");
fn(3);
var copyFn = fn;
console.log("running copyFn");
copyFn(3);
fn = function() { console.log("done"); };
console.log("fn after reassignment");
fn(3);
console.log("copyFn after reassignment of fn");
copyFn(3);https://stackoverflow.com/questions/7065120
复制相似问题