如何在JavaScript中正确使用模块模式?

时间:2012-05-24 13:05:58

标签: javascript oop design-patterns

在我的公司,我们有一个调查框架来帮助利益相关者创建调查,我正在尝试创建一个可重复使用的对象,这将允许团队成员轻松设置调查的特定问题的宽度 - 他们有时可以根据答案的长度有点压扁。我正在尝试使用模块和构造函数模式的组合,但不确定我是否正确地将其关闭。有没有更好的方法来编写我的代码?

        var WidthIncreaser = (function(){
            return function (element, words, width) {

                var element = $(element);
                var re = new RegExp(words, 'gi');

                return {
                    init: function() {
                        if (element.text().match(re)) {
                            element.width(width);
                        }
                    }
                };
            };
        })();

        var tr = new WidthIncreaser('td.choicev-question:first', 'Applicable from the', 400);
        tr.init();

这个想法是,有人可以创建一个WidthIncreaser的新实例,并传入一个元素,一个与问题文本相匹配的字符串,这样就可以找到正确的问题,并将问题的宽度设置为。

提前感谢您的建议!

3 个答案:

答案 0 :(得分:1)

你是双重包装的东西。无论如何,我看到的常见模块模式只是一个返回带闭包的对象的函数。

不需要new关键字也不需要立即执行功能。当只生成一个对象并直接分配给一个变量时,通常使用立即函数。在您的情况下,您想要制作“实例”。

var WidthIncreaser = function(element, words, width) {

    var element = $(element),
        re = new RegExp(words, 'gi');

    return {
        init: function() {
            if (element.text().match(re)) {
                element.width(width);
            }
        }
    };
};

var tr = WidthIncreaser('td.choicev-question:first', 'Applicable from the', 400);

tr.init();​

答案 1 :(得分:0)

我使用的模块模式通常如下所示:

var myModule = (function () {
    var myPrivateVar = 'foo';
    var myPrivateFunc = function () {
        console.log('bar');
    };

    return {
        myPublicFunc: function () {
            console.log(myPrivateVar);
        }
    };
}) ();

然后就会这样使用:

myModule.myPublicFunc();

答案 2 :(得分:0)

我认为你实际上并不需要“模块模式”。你可以利用闭包的优点:

function WidthIncreaser(element, words, width) {
    element = $(element);
    var re = new RegExp(words, 'gi');

    this.init = function () {
        if (element.text().match(re)) {
            element.width(width);
        }
    }
}

var tr = new WidthIncreaser('td.choicev-question:first', 'Applicable from the', 400);

tr.init();

当然,在这种情况下你不需要init,因为你可以将所有内容放在ctor中,但我认为这只是一个例子,也许你需要延迟初始化。

通过这种方式,您可以保留prototype个链,并且您可以使用以下语句:

trofofof WidthIncreaser // true

会有效。

此外,您还可以使用不需要访问范围变量的方法填充prototype,至少不能直接填充:

WidthIncreaser.prototype.doSomething = function(){/ * .. * /}

例如,如果因为交叉浏览限制而无法使用getter和setter,那么你可以使用这样的函数:

function WidthIncreaser(element, words, width) {
    element = $(element);
    var re = new RegExp(words, 'gi');

    this.element = function() { return element };

    this.init = function () {
        if (element.text().match(re)) {
            element.width(width);
        }
    }
}

WidthIncreaser.prototype.reset = function () {
    this.element().text("")
}

所以基本上你可以从外面检索元素,但它是只读的,WidthIncreaser只能在实例化过程中设置元素。

修改:我复制并粘贴了init,当然它不适用于re的依赖项,所以这是一个很好的例子来说明这种方法。