揭示模块模式的缺点

Tom*_*mer 13 javascript design-patterns revealing-module-pattern knockout.js

我最近熟悉了Revealing Module模式,并且我已经阅读了很多关于它的文章.

这似乎是一个非常好的模式,我想在我拥有的一个大项目中开始使用它.在我正在使用的项目中:Jquery,KO,requirejs,Jquery Mobile,JayData.在我看来它似乎非常适合KO ViewModels.

具体来说我想使用它的THIS版本.

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

在开始使用它之前我应该​​考虑什么?

I-L*_*Kuo 15

Revealing Module Pattern(RMP)创建的对象在覆盖方面表现不佳.因此,使用RMP制作的对象不能很好地用作原型.因此,如果您正在使用RMP来创建将在继承链中使用的对象,那就不要.这种观点是我自己的,与那些揭示原型模式的支持者相对立.

要查看错误的继承行为,请参阅以下网址构建器示例:

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

  return {
    urlBase: _urlBase,
    build: _build
  }
}
Run Code Online (Sandbox Code Playgroud)

撇开为什么要将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"
Run Code Online (Sandbox Code Playgroud)

将行为与以下URL构建器实现进行对比

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"
Run Code Online (Sandbox Code Playgroud)

行为正确.

您可以使用此范围更正显示模块模式的行为,如下所示

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

  return {
    urlBase: _urlBase,
    build: _build
  }
}
Run Code Online (Sandbox Code Playgroud)

但这相当违背了揭示模块模式的目的.有关详细信息,请参阅我的博客文章http://ilinkuo.wordpress.com/2013/12/28/defining-return-object-literals-in-javascript/


Tom*_*mer 4

我读了 @nemesv 引用我的文章(谢谢:)),我认为还有一个没有提到的缺点,所以我想我将其添加到此处以供参考。以下是该文章的引用:

缺点

此模式的缺点是,如果私有函数引用公共函数,则在需要修补程序时无法覆盖该公共函数。这是因为私有函数将继续引用私有实现,并且该模式不适用于公共成员,仅适用于函数。

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

因此,使用 Revealing Module 模式创建的模块可能比使用原始 Module 模式创建的模块更脆弱,因此在使用过程中应小心。

我的补充:

您不能将继承与此模式一起使用。例如:

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

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

InheritingObj.prototype = new Obj();

InheritingObj.prototype.constructor = InheritingObj;
Run Code Online (Sandbox Code Playgroud)

这是 js 中继承的一个简单示例,但是当使用揭示原型模式(存档于此处)时,您需要执行以下操作:

InheritingObj.prototype = (function(){
    //some prototype stuff here
}());
Run Code Online (Sandbox Code Playgroud)

这将覆盖你的继承。