Javascript 关于一种一次性自定义函数模式

Javascript 关于一种一次性自定义函数模式,javascript,closures,Javascript,Closures,考虑以下模式: function foo /* aka outer_foo */ () { // === stage 1 === // declaration and initialization of closure variables var ... <CLOSURE_VARS> ...; // initialization of CLOSURE_VARS // (possibly expensive and/or depending

考虑以下模式:

function foo /* aka outer_foo */ () {

    // === stage 1 ===
    // declaration and initialization of closure variables

    var ... <CLOSURE_VARS> ...;

    // initialization of CLOSURE_VARS
    // (possibly expensive and/or depending on values known only at run-time)


    // === stage 2 ===
    // one-time redefinition of foo

    foo = function /* inner_foo */ ( arg0, ... ) {
        var results;

        // code computing value of results based on CLOSURE_VARS, arg0, ...

        // foo is never modified here

        return results;
    };


    // === stage 3 ===
    // invocation of inner function and returning of result

    return foo.apply( this, arguments );
}
在此变体中,最终分配给
foo
的函数取决于运行时执行的一些测试


2这里很容易规定,
foo
不仅必须在outer\u foo中准确地重新定义一次,而且必须“决定性地”重新定义。当然,在
foo
的最终设置中,任何对“决定论”的偏离(无论如何定义它)都只会增加代码运行时行为的复杂性。不幸的是,我不知道如何使这一规定准确无误,而不陷入律师们错综复杂的琐事中。我所能做的最好的事情就是加上一句含糊不清的话“越确定越好”,希望读者明白我的意思。然而,这一附加规定的唯一用途是排除反常但完全不现实的情况(例如,
foo
的最终值取决于随机过程的结果),因此我省略了它。

我可以想到另外两点,您应该注意:

  • 性能。编译器就像你提到的人一样。他们中的一些人会对这种模式感到困惑,他们可能无法像使用不同的模式那样对其进行优化。这可能是个问题,也可能不是,但您应该确保对其进行测试
  • 违约合同。你说你希望外施福最多被处决一次。情况可能并非如此!有人可能会将它传递给其他人,并将它的引用放在某个地方,以便在调用时不会无法访问它。当然,这不太可能,但根据您的需求,您可能希望防范它。
    毕竟,这是一种破碎的设计,因为仅仅是一个别名(
    var f=foo;f()
    )永远不会改变功能。确保所有消费者/用户都知道你在做什么,这样他们就不会被绊倒
function foo /* aka outer_foo */ () {
    var inner_foo, ... <CLOSURE_VARS> ...;

    if ( some_deterministic_test() ) {
        inner_foo = function ( arg0, ... ) {
            // etc.
        }
    }
    else {
        inner_foo = function ( arg0, ... ) {
            // etc.
        }
    }


    foo = inner_foo;

    return foo.apply( this, arguments );
}