当使用JavaScript模块模式时,我如何从私有方法中调用公共方法?

9
我想从一个私有方法中调用一个公共方法,但是属性"this"指的是窗口对象。
请注意,我正在尝试应用模块模式。您可以在jsfiddle.net找到一个可工作的代码示例。
// how can i access a public method from a private one?
// (in this example publicAlert from privateMethod)
// this refers to the window object.

$(function() {
var modulePattern = (function($)
{
    var privateMethod = function()
    {
        appendText("called privateMethod()");
        this.publicAlert();
    };

    var appendText = function(texToAppend)
    {
        var text = $('#output').text() + " | " + texToAppend;
        $('#output').text(text);
    };

    return {
        publicMethod : function()
        {
            appendText("called publicMethod()");
            privateMethod();
        },

        publicAlert : function()
        {
            alert("publicAlert");
        }
    };
});

mp = new modulePattern($);
mp.publicMethod();
});

是的,你没有正确使用模块模式。你应该立即执行匿名函数,而不是使用“new”,也不应该使用“this”关键字。你也不需要将模块包装在jquery的ready处理程序中,只需调用它。请参见此链接:http://jsfiddle.net/sVxvz/ - david
1
好的答案已经在这里了:https://dev59.com/m3NA5IYBdhLWcg3wC5Th - user11153
2个回答

11

如果您想要这样做,您需要像声明私有函数一样声明“public”函数,然后将其公开为公共函数。如下所示:

$(function() {
    var modulePattern = (function($) {
        var privateMethod = function() {
            appendText("called privateMethod()");
            publicAlert();
        };

        var appendText = function(text) {
            var text2 = $('#output').text() + " | " + text;
            $('#output').text(text2);
        };

        var publicAlert = function(){
            alert("publicAlert");            
        };

        return {
            publicMethod: function() {
                appendText("called publicMethod()");
                privateMethod();
            },

            publicAlert: publicAlert
        };
    });

    mp = new modulePattern($);
    mp.publicMethod();
});
[编辑] 我还鼓励你养成在jsfiddle页面顶部点击“jslint”按钮的习惯,你的代码缺少了一些分号,并且你在appendText函数内重新声明了“text”变量(它已经被传递进来了)。 另外,你正在以与我学习的方式稍有不同的方式使用模块模式。 你有参考资料的链接吗?
以下是我按照自己所知道的方式编写模块模式的示例:http://jsfiddle.net/sVxvz/ [/编辑]
此外,如果你正确使用模块模式,你可以通过使用模块名来引用公共函数,像这样:
var testModule = (function($) {
    var privateMethod = function() {
        appendText("called privateMethod()");
        testModule.publicAlert();
    };

    var appendText = function(text) {
        var text2 = $('#output').text() + " | " + text;
        $('#output').text(text2);
    };

    return {
        publicMethod: function() {
            appendText("called publicMethod()");
            privateMethod();
        },
        publicAlert: function() {
            alert("publicAlert");
        }
    };
}(jQuery));

$(function() {
    testModule.publicMethod();
});

但我并不是很喜欢这种方式,因为公共方法可能会被重写。 有人可能会这样做:testModule.publicAlert = function(){EVIL CODE OF DOOM;};,而你的内部机制将会快乐地执行它。


感谢您的反馈。非常抱歉代码不够规范,因为我一直在思考我的问题,所以完全忘记了jslint按钮 :)以下是我用作模式参考的两个来源:yuiblogajaxian - Ota
我认为你的解决方案将是最简单的,但除了将publicAlert方法从private更改为public之外,是否有一种方法可以注入正确的作用域来处理“this”? - Ota
是的,在这两个链接中,它们都自动执行函数,而你没有这样做。你有检查我在底部添加的链接吗?http://jsfiddle.net/sVxvz/ 另外,subhaze,我没有重复定义公共方法,它们只被定义一次,然后通过返回对象公开。这与你所做的类似,只不过你在返回之前构建了返回对象,这使得内部函数可以看到它。非常聪明! - david
@david,模式在哪里说必须自动执行呢?我认为这是开放给开发者的。基本上,当您自动执行时,会创建一个单例。在init方法中将“this”分配给名为“that”的变量,并使用“that”获取正确的范围是否可能?但是,与发布的两种解决方案相比,该解决方案听起来要复杂得多。我无法决定哪种方法更好,您发布的还是subhaze发布的。 :) - Ota
因为自动执行是该模式的重要部分。你不是创建一个新对象,而是创建一个匿名函数作用域,立即执行它以创建一个封闭内部“私有”变量的闭包,然后返回一个特别定制的对象,以允许有限访问被困在闭包中的函数。 - david
显示剩余3条评论

0

我知道这和模块模式有些不同,但我认为它仍然提供了封装的相同优点。公共方法声明为:

this.methodName = function(){...}

变量 $this 被赋值为当前实例(this),因此您可以在私有(或公共)方法中使用它来访问该实例上的任何方法或属性。

分叉:

http://jsfiddle.net/FNjJq/


你所做的只是创建一个新对象,这并不是模块模式。 - david
据我所知,您只是在对象“modulePattern”内创建一个新对象“this”。因此,您不再应用该模式。 - Ota

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接