11

我最近熟悉了揭示模块模式,并且我阅读了很多关于它的文章。揭示模块模式缺点

这似乎是一个很好的模式,我想开始在我有一个大项目中使用它。在我使用的项目中:Jquery,KO,requirejs,Jquery Mobile,JayData。在我看来,它很适合KO ViewModels。我想用THIS这个版本。

我无法找到的一件事是使用这种模式的缺点,是因为没有任何(我觉得很难相信)?

开始使用前应该考虑什么?

+2

选中此文章:http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript最后有一个缺点部分。 – nemesv

+0

定义模块模式还克服了模块模式和显示模式的一些缺点(如与返回语句的紧密耦合,公共和私有函数如何声明,私有和公共子例程的非声明性命名空间以及对象的混合使用字面与返回语句):http://github.com/tfmontague/definitive-module-pattern – tfmontague

回答

4

我读过@nemesv引用了我的文章(谢谢:)),我认为还有一个缺点没有提到,所以我想我会在这里添加它作为参考。下面是文章报价:

缺点

这种模式的缺点是,如果一个私有函数是指 公共职能,公共职能不能被覆盖,如果补丁 是必要。这是因为私有函数将继续以 引用私有实现,并且该模式不适用于 公共成员,仅适用于函数。

引用私有变量的公共对象成员也是 受上述无补丁规则注释的约束。

因此,使用“展示模块”模式 创建的模块可能比使用原始模块 模式创建的模块更脆弱,因此在使用过程中应该小心。

而且我另外:

不能使用继承这种模式。例如:

var Obj = function(){ 
    //do some constructor stuff 
} 

var InheritingObj = function(){ 
    //do some constructor stuff 
} 

InheritingObj.prototype = new Obj(); 

InheritingObj.prototype.constructor = InheritingObj; 

这对于JS继承一个简单的例子,但使用Revealing Prototype Pattern当你需要这样做:

InheritingObj.prototype = (function(){ 
    //some prototype stuff here 
}()); 

这将覆盖你继承。

+0

它看起来像它与Object.create(urlBuilder)完美的工作;继承的另一种方法是这样http://jsfiddle.net/d0n7kfmx/你怎么看? – user2734550

13

揭示模块模式(RMP)创建的对象在覆盖方面表现不佳。结果,使用RMP制造的物体不能很好地用作原型。因此,如果您使用RMP创建要在继承链中使用的对象,则不要这样做。 这个观点是我自己的观点,反对揭示原型模式的支持者。

要看到坏的继承行为,采取了网址构建器的下面的例子:

function rmpUrlBuilder(){ 
    var _urlBase = "http://my.default.domain/"; 
    var _build = function(relUrl){ 
    return _urlBase + relUrl; 
    }; 

    return { 
    urlBase: _urlBase, 
    build: _build 
    } 
} 

撇开为什么你会使用RMP对于没有专用部件对象的问题,注意,如果您取回返回的对象,并用“http://stackoverflow.com”覆盖urlBase,你会期望build()的行为适当地改变。它并不像看到以下内容:

var builder = new rmpUrlBuilder(); 
builder.urlBase = "http://stackoverflow.com"; 
console.log(builder.build("/questions"); // prints "http://my.default.domain/questions" not "http://stackoverflow.com/questions" 

对比度与下列网址构建器实现

function urlBuilder = function(){ 
    return { 
    urlBase: "http://my.default.domain/". 
    build: function(relUrl){ return this.urlBase + relUrl;} 
    } 
} 

var builder = new urlBuilder(); 
builder.urlBase = "http://stackoverflow.com"; 
console.log(builder.build()); // prints "http://stackoverflow.com/questions" 

其行为正确的行为。

您可以使用此范围作为修正透露出模块模式的行为如下

function rmpUrlBuilder(){ 
    var _urlBase = "http://my.default.domain/"; 
    var _build = function(relUrl){ 
    return this.urlBase + relUrl; 
    }; 

    return { 
    urlBase: _urlBase, 
    build: _build 
    } 
} 

但宁可失败透露出模块模式的目的。有关详细信息,请参见我的博客文章http://ilinkuo.wordpress.com/2013/12/28/defining-return-object-literals-in-javascript/

-2

其他缺点与所述显示模块模式包括:

  1. 与Return语句的公共职能紧密耦合
  2. 对象的混合使用字面公共职能和私人功能
  3. 独立宣言

我推荐使用明确的模块模式在显露的模块模式 (https://github.com/tfmontague/definitive-module-pattern

+0

我不会推荐这种模式,因为它与揭示模块模式没有本质区别。它与被接受的答案中的重写和原型有相同的缺点。 –

+0

问题是关于“揭示模块”模式的缺点。这不是关于使用模块模式的决定。 – tfmontague