【问题标题】:Javascript - using arguments for closure, bad or good?Javascript - 使用闭包参数,好还是坏?
【发布时间】:2013-08-07 09:04:48
【问题描述】:

让我们考虑简单的单例实现:

var singleton = function (Constructor) {
    var singleton;
    return function () {
        if (!singleton) {
            singleton = new Constructor();
        }
        return singleton;
    };
};

我们可以将 singleton 变量的声明移到参数中:

var singleton = function (Constructor, singleton) {
    return function () {
        if (!singleton) {
            singleton = new Constructor();
        }
        return singleton;
    };
};

所以我只是对副作用感到好奇。

再举一个例子:

var counter = (function (i) {
    return function () {
        i = (i || 0) + 1;
        return i;
    };
}());

【问题讨论】:

  • counter 的示例似乎不必要地复杂,每次调用时使用(i||0)。在外部函数中使用var i = 0; 会更容易阅读并且更高效,然后内部函数可以是单行:return ++i;

标签: javascript closures private


【解决方案1】:

我们可以将单例变量的声明移到参数中

首先,让我们在相同的几行代码中使用相同的符号 (singleton) 来表示两个完全不同的事物,从而使讨论这个问题成为可能。

这是您重命名的第二个示例:

var singleton = function (Constructor, instance) {
    return function () {
        if (!instance) {
            instance = new Constructor();
        }
        return instance;
    };
};

如果你这样做了,那么使用两个参数调用 singleton 函数将指定 instance,从而使传递 Constructor 毫无意义——Constructor 永远不会被 singleton 调用(同样,如果你传入两个参数 [并且第二个参数是真实的])。所以这样做会有点奇怪。

但是您询问了副作用。如果您分配给函数内的正式参数,则不会涉及 外部 效果。例如,它对函数之外没有任何影响:

function foo(arg) {
    arg = 67;
}
var a = 42;
foo(a);
console.log(a); // Still 42

但是,在非严格模式下,分配给一个参数而不是一个局部变量确实有一个小的成本,因为这涉及到开销:它与魔术 arguments 伪数组有关。在非严格模式下,函数的形式参数和arguments 伪数组之间存在联系:

function foo(a, b) {
    console.log(a);
    console.log(b);
    b = 42;
    console.log(arguments[1]);
}

如果我们这样称呼它:

foo(1, 2);

我们看到

1
2
42

注意魔术:分配给形式参数b 更新了伪数组arguments。 (它也适用于其他方式。)该链接的运行时成本很小但确实很实际。

(在严格模式下,没有链接,正因如此。)

【讨论】:

  • 想补充一点,它很复杂,可以覆盖构造函数并破坏整个单例。
【解决方案2】:

closure 而言,这两种实现方式没有区别。但是,在第一个示例中,调用者不能设置单例。

我将在两种实现之间进行选择,这取决于是否可以在这些示例函数之外创建单例。如果可以,请使用model 2,否则请使用model 1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-04
    • 1970-01-01
    • 1970-01-01
    • 2012-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多