如何在JavaScript中使用显示模块模式


78

我偶然发现了这篇文章:JavaScript的Revealing Module Pattern。我想在我的项目中使用它。

假设我有一个函数,abc并且正在主JavaScript文件中调用该函数。

这种模式会使事情有所不同吗?谁能告诉我这种模式的基本示例?


3
对我来说,这篇文章是到目前为止我所看到的最好的解释。
Mohammad Sepahvand

2
当您可以使用确定性模块模式时,为什么还要使用显示模块模式?github.com/tfmontague/definitive-module-pattern
tfmontague 2014年

Answers:


98

一个小例子:

var revealed = function(){
   var a = [1,2,3];
   function abc(){
     return (a[0]*a[1])+a[2];
   }

   return {
      name: 'revealed',
      abcfn: abc
   }
}();

在匿名函数中启动,该匿名函数被赋予revealed一个值,a并且abc对该函数是私有的。函数返回的是带有name属性和abcfn属性的对象文字,该属性是对的引用abc function。在abc function使用私有变量a。这一切都可以通过使用闭包来完成(该函数范围内的所有内容都可以被该同一函数中的其他所有内容引用)。

显示的用法:

alert(revealed.name);    //=> 'revealed'
alert(revealed.abcfn()); //=> 5 (1*2+3)

8
这种模式改变了我的生活!
klewis 2012年

6
我知道这很旧,但是abc()的返回值缺少括号=]
Fillip Peyton 2013年

当您可以使用确定性模块模式时,为什么还要使用显示模块模式?github.com/tfmontague/definitive-module-pattern
tfmontague 2014年

如何创建显示的新实例?
Neon Warge,2015年

@NeonWarge:你不知道。该函数不是构造函数。它返回一个对象文字,其中aabc被封闭。
KooiInc 2015年

23

DC = Douglas Crockford
RMP =显示模块模式

DC和RMP之间的差异主要是组织/可读性

示例本身是在文章中提出的吗?您到底要问什么,因为这些东西与文件无关,而与闭包无关。

您将所有内容放在一个闭包(函数)中,仅公开您希望访问的那些部分。DC的风格和RMP之间的区别是,在第一个功能在不同的地方被定义而在RMP,他们在同一个地方总是定义,然后再把显露公众对象文本。

因此,在DC和RMP中,您具有:

  • 可以定义私有部分(变量和函数)的闭包
  • 私人部分
  • 公开结果,定义了公开可见的功能和变量(状态)

这两种模式仅在可读性上有所不同。在DC情况下,您无法始终知道在何处定义某些功能,但是在RMP中,您始终知道一切都在私有部分中。


1
DC和RMP并不是完全一样的-继承方面两者是非常不同的。见stackoverflow.com/questions/21925720/...例如
I-林廓


6

作者所谓的“道格拉斯·克罗克福德创建对象的模式”实际上是由Richard Cornford等人开发的模块模式。请参阅http://groups.google.com/group/comp.lang.javascript/msg/9f58bd11bd67d937

例如,有很多。阅读以下文章,并点击一些链接:http : //peter.michaux.ca/articles/module-pattern-provides-no-privacy-at-least-not-in-javascript-tm


我重贴了我的帖子,如果还有问题,请告诉我:)
alex 2012年

这些事情随着时间的流逝如何有趣。“公开”版本已经由MyLibrary的David Mark使用了一段时间,我对“非公开”版本没有任何问题,因此我可以使用它。:-)
RobG 2012年

1

我喜欢将揭示性模块模式单例模式混合使用,以便我可以利用模块模式的好处来保持结构化代码:

var MyFunction = function(){

    var _ = {
       Init: function(){
          _.Config.foo = "hello world";
       },
       Config:{
          foo:null
       },
       ShowAlert:function(){
          alert(_.Config.foo);
       }
    }

    return {
        Init: _.Init,
        ShowAlert: _.ShowAlert
    };
}();

MyFunction.Init();
MyFunction.ShowAlert();

我在博客上写了更多有关此的信息:

http://curtistimson.co.uk/js/mixing-revealing-module-and-singleton-javascript-patterns/


1

只需添加:使用这种模式,最好将全局依赖项作为参数/参数传递,以便它们是显式的。您不必执行此操作,但是乍一看就很清楚您的模块需要什么。例如:

var myModule = (function ($, loadModule) {
  "use strict";
})(jQuery, load);

在此示例中,您可以在第一行立即看到您的模块使用jQuery和其他负责加载功能的模块。


0

对于模块外部的代码,它没有什么区别。在该文章的所有3种情况下,方法都以相同的方式调用。但是模块本身的结构在内部是不同的。

从结构上来说,Crockford的模块模式和他们所说的“显示模块模式”几乎是同一回事。唯一的区别是,它们首先将方法分配给本地var,以使其更具可读性。但是实际上并没有什么特别的,您的链接中有一些示例。


在覆盖方面,显示模块模式返回的对象的行为与Douglas Crockford的模块模式不同(请参见addyosmani.com/resources/essentialjsdesignpatterns/book/…的Addy Osmani警告)。
I-Lin Kuo 2015年

0

揭露性模块的基本概念是,你有一个Object封装了数据和行为:

var Module = (function(){
    var privateStuff = {};
    var publicStuff = {};

    return publicStuff;
})();

但是,使用此模式时应采用一些最佳做法。这是一个Modulus带有一些属性的模块(“ ”),用于演示,它采用了以下一些实践:

function AbstractSomeClass(id) {
    this.id = id;
    return this;
}

var Modulus = (new (function SomeClass() {
    var thus = this;

    function NameClass(name){
        this.value = thus.name || name;
    }

    AbstractSomeClass.call(this, 998);

    this.name = 'Touring';
    this.name = ( new NameClass('Hofstadter') ).value;

    return {
        id: this.id,
        name: this.name
    };
})());

注意(new (function SomeClass(){ ... })());语法。这样使用new可以让您在闭包内部使用this关键字。如果您需要从另一个类()继承属性,这很方便-但是,您仍然需要显示您想公开的属性,例如:AbstractSomeClass.call(this, 998);

return {
    id: this.id,
    name: this.name
};

还要注意,我们分配thisthus-,这使我们可以在this具有自己this范围(this.value = thus.name || name;)的子类中使用Parent-

同样,这些只是建议的一些约定和最佳实践。


0

这是揭示模块模式的小例子。

它提供了一种像类一样声明私有和公共功能的功能,这是这种模式的主要好处,如果我们不想公开某些可从全局访问的功能,则可以将其私有化,并将其设为公开。是如何实现私有和公共功能的示例。此外,它是一个可自我执行的代码块。

  var Calculator = (function () {

        var num1 = 10;
        var num2=5
        var _abc = function () {
            return num1 - num2;
        };

        var _mulFunc = function () {
            return num1 * num2;
        };

        var _divFunc = function () {
            return num1/num2;
        };

        return {
           //public scope
            abc: _abc,
            mulFunc:_mulFunc
         };

    })();

alert(Calculator.abc()); 它返回5

alert(Calculator.mulFunc()); 它返回50

__divFunc()将无法访问,因为它处于私有范围内。我们只能访问在返回对象内部声明的那些函数, 因为它是公共函数表示形式


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.