【问题标题】:Can a JavaScript function return itself?JavaScript 函数可以返回自身吗?
【发布时间】:2011-08-05 16:21:09
【问题描述】:

我可以写一个返回自身的函数吗?

我正在阅读一些关于闭包的描述 - see Example 6 - 其中一个函数正在返回一个函数,因此您可以将 func()(); 作为有效的 JavaScript 调用。

所以我想知道一个函数能否以这样一种方式返回自身,您可以像这样将它无限期地链接到自身:

func(arg)(other_arg)()(blah);

使用arguments 对象,被调用者还是调用者?

【问题讨论】:

标签: javascript function self


【解决方案1】:

有 2-3 种方式。如您所说,一种是使用arguments.callee。如果您正在处理未存储分配给某个变量(您知道)的匿名函数,这可能是唯一的方法:

(function() {
    return arguments.callee;
})()()()().... ;

第二个是使用函数名

function namedFunc() {
    return namedFunc;
}
namedFunc()()()().... ;

最后一个是使用分配给变量的匿名函数,但你必须知道变量,所以在这种情况下我看不出有什么理由,为什么你不能只给函数一个名字,并使用上面的方法

var storedFunc = function() {
    return storedFunc;
};
storedFunc()()()().... ;

它们在功能上都是相同的,但callee 是最简单的。

编辑:我同意 SLaks;我也不能推荐它

【讨论】:

  • 值得注意的是 arguments.callee 在 ES5 Strict ejohn.org/blog/ecmascript-5-strict-mode-json-and-more 中抛出错误
  • @abbotto 方法 3 对我来说效果很好,但是方法 2 是“正确”的方法。至于弃用,请注意这个答案是 5 岁
  • @Flambino,你是对的。方法 1:通常应该完全避免,因为 arguments.callee 已被弃用。请参阅:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… 方法 2:这是在 JS 中进行递归函数调用的最佳方式,因为该函数不是匿名的,并且它的名称会显示在堆栈跟踪中。
  • @Flambino @MarkFox @abbotto 可以结合方法 1 和 2 来消除被调用方的使用 (function X() {return X;})()()()().... ; 从而减轻弃用问题。函数名也出现在堆栈跟踪中。它简洁、合规且不污染命名空间。
【解决方案2】:

是的。
return arguments.callee;


但是,这可能会导致代码非常混乱;我不推荐它。

【讨论】:

  • 我只是命名函数,而不是使用arguments.callee,原因有两个:1.函数通常通过实现进行优化,如果你不使用arguments对象,它就不会一般创建(执行上下文会更快初始化)-当然,如果函数使用eval,通常无法优化-。 2. arguments 对象在 ES5 严格模式下发生了变化,arguments.callee 属性已被禁止(同样也是出于优化和安全考虑),所以基本上是为了编写 future-proof 代码,我建议只命名函数。 :)
  • @CMS:您确定不再允许callee 吗?我以为是caller
  • 两者都是不允许的,caller AFAIR 实际上从来都不是规范的一部分,但它得到了许多实现的支持,这就是为什么在 ES5 上,对于严格的功能,callercallee分配给thrower function,参见10.6 Arguments Object中的步骤14
  • 另外,检查这个简单的benchmark test 以了解arguments 对象的创建如何影响性能。顺便说一句,caller 属性非常危险,它允许在某些实现中“破坏”闭包,例如在 Spidermonkey 中,一些技术like this one 允许泄漏私有范围的函数。
【解决方案3】:

您可以按照以下方式进行操作:

// Do definition and execution at the same time.
var someFunction = (function someFunction() {

    // do stuff
    return someFunction
 })();

 console.log(someFunction)

arguments.callee 在 JavaScript 严格模式下不受支持。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode

【讨论】:

    【解决方案4】:

    以上所有的甚至是排序器:

    f=()=>f

    【讨论】:

    • 你将如何向函数添加任何逻辑?
    • 在没有 const/let/var 的情况下为变量定义任何内容是一种不好的做法,而且它在严格模式下也不起作用。 @Sam,您可以使用 {} f.e 将逻辑添加到此箭头函数。 const f = () => { console.log('test'); return f }
    【解决方案5】:

    有一种简单的方法可以做到这一点:

    let intArr = [];
    function mul(x){
        if(!x){
            return intArr.reduce((prev, curr) => prev * curr)
        }
        intArr.push(x);
        return mul;
    }
    
    console.log(mul(2)(4)(2)()); => outputs 16
    

    【讨论】:

    • -1 的原因,这不是原帖中所要求的
    • @micnic OP 要求返回自身的函数。上面的函数返回自己。我错过了什么吗?
    • @SamuelEbert,是的,这个函数会返回自己,但也有函数式的臃肿,这对问题的上下文没有用,而是专注于那个额外的函数式。就像我会问一个动词“to be”的用法示例,我会得到莎士比亚的回应“Hamlet”,甚至没有指出动词“to be”的示例在文本中的位置。
    • @micnic,感谢您的澄清。我实际上同意你的看法。 :)
    【解决方案6】:

    也可以只返回自调用函数的参数,例如

    console.log( (function(a) {  return a; })(1) ); // returns 1
    

    【讨论】:

    • 为什么?他问了一些返回函数(本身)的东西,我给了一个。这很混乱吗?
    猜你喜欢
    • 2019-04-02
    • 1970-01-01
    • 1970-01-01
    • 2013-07-06
    • 1970-01-01
    • 2018-09-25
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    相关资源
    最近更新 更多