【问题标题】:Module pattern: setting module-wide arrays模块模式:设置模块范围的数组
【发布时间】:2014-04-23 17:18:46
【问题描述】:

尽管阅读了关于 Javascript 模块模式的 all the usual 教程,但仍有一些关于范围界定的内容我显然不明白。

pushing 到一个模块范围的列表可以满足我的期望。使用 = 设置模块范围的列表不会。我在这里做错了什么?

var MODULE = MODULE || {};

MODULE.Submodule = (function(){
    var foo = [],
        bar = [];

    var init = function() {
        foo = ['a','b','c']; // This doesn't set MODULE.Submodule.foo
        bar.push('a'); // But this works as expected
        console.log('foo: ' + MODULE.Submodule.foo); // foo:
        console.log('bar: ' + MODULE.Submodule.bar); // bar: a
    }

    return {
        init: init,
        foo: foo,
        bar: bar
    }
}());

MODULE.Submodule.init();

【问题讨论】:

标签: javascript design-patterns module-pattern


【解决方案1】:

这个 JSFiddle http://jsfiddle.net/SwBLk/1/ 可能有助于解释正在发生的事情:

var MODULE = MODULE || {};

MODULE.Submodule = (function(){
var foo = [],
    bar = [];

var init = function() {
    console.log(MODULE.Submodule.foo === foo);
    foo = ['a','b','c']; // This doesn't set MODULE.Submodule.foo
    console.log(MODULE.Submodule.foo === foo);
    bar.push('a'); // But this works as expected

    console.log('foo: ' + MODULE.Submodule.foo); // foo:
    console.log('bar: ' + MODULE.Submodule.bar); // bar: a
}

return {
    init: init,
    foo: foo,
    bar: bar
}
}());

MODULE.Submodule.init();

第一个布尔检查返回 TRUE,因为两个对象引用同一个对象。 第二个布尔检查返回 FALSE,因为您已将 foo 替换为新对象,并且引用不再指向同一个底层对象。

当您将新数组重新分配给它时,您将用对新数组的引用替换 foo 数组。

当您执行 IIFE 时,您在 return 语句中分配了一个对“foo”非常特定版本的引用。这是您在调用 MODULE.Submodule.foo 时访问的参考。当您进入并替换 foo = [ "a", ... ] 时,您正在替换对象 foo,但不会替换 MODULE.Submodule 对象中对它的引用。

编辑:你如何解决这个问题?

1) 理想情况下,您不要替换整个数组,而只需在 init() 调用时清除并重新初始化它:

MODULE.Submodule = (function(){
var foo = [],
    bar = [];

var init = function() {
    // Clear our the array if it already contains data (in case your calling "init" more than once)
    // This method is documented to be the fastest way to clear out an array, referenced here:
    // http://stackoverflow.com/questions/1232040/how-to-empty-an-array-in-javascript
    while(foo.length > 0) {
        foo.pop();
    }

    foo.push('a');
    foo.push('b');
    foo.push('c');

    bar.push('a'); // But this works as expected

    console.log('foo: ' + MODULE.Submodule.foo); // foo:
    console.log('bar: ' + MODULE.Submodule.bar); // bar: a
}

2) 您的第二个选择是使用我所说的“动态吸气剂”(工作小提琴:http://jsfiddle.net/6zVcP/):

var MODULE = MODULE || {};

MODULE.Submodule = (function(){
var foo = [],
    bar = [];

var init = function() {
    foo = ['a','b','c']; // This doesn't set MODULE.Submodule.foo
    bar.push('a'); // But this works as expected

    console.log('foo: ' + MODULE.Submodule.foo()); // foo:
    console.log('bar: ' + MODULE.Submodule.bar()); // bar: a
}

var modify = function()
{
    foo = [];
    foo.push("test");
}

return {
    init: init,
    modifyArrays: modify,
    foo: function() { return foo; },
    bar: function() { return bar; }
}
}());

MODULE.Submodule.init();
MODULE.Submodule.modifyArrays();
console.log(MODULE.Submodule.foo());

这允许你对 foo 对象做任何你想做的事情,而 getter 将始终返回最新的引用。

【讨论】:

  • 解释发生了什么的好方法。我怎样才能绕过它?
  • 好吧,理想情况下您不会替换数组,您只需清空并初始化相同的数组对象。如果这不是一个选项,那么您需要一个动态吸气剂。编辑答案以解释。
猜你喜欢
  • 1970-01-01
  • 2021-08-30
  • 1970-01-01
  • 1970-01-01
  • 2014-10-03
  • 2023-03-20
  • 1970-01-01
  • 2015-11-01
  • 1970-01-01
相关资源
最近更新 更多