模块模式中的这个关键字?

时间:2012-05-09 01:12:52

标签: javascript design-patterns global-object

我刚刚开始在一家新公司工作,并注意到在他们的很多JS中我看起来完全没错。我有点犹豫要提起它而不确认这是错的,因为我很小,我不是JS专家,这只是我的第二天,我不想看起来很愚蠢。

所以,通常我希望模块模式看起来像:

MODULENAME = MODULENAME || {};

MODULENAME.SUBMODULENAME = (function() {
    var bla = {};

    bla.somefunction = function() {
        //do stuff
    };

    //add more stuff to bla
    return bla;
}());

他们的代码是:

MODULENAME = MODULENAME || {};

MODULENAME.SUBMODULENAME = (function() {
    var that = this;

    that.somefunction = function() {
        //do stuff
    };

    //add more stuff to that
    return that;
}());

现在当然因为函数没有被new关键字或方法作为构造函数调用,this绑定到window并且它们正在定义{{ 1}}为that。因此,他们基本上将所有内容转储到全局对象中,并且所有子模块名称实际上都是this的别名。有没有理由有人想要这样做?或者这在我看来真的是错误的吗?

修改

我在将window放在子模块定义之前犯了一个错误,最初我写了一些略有不同的内容,忘了删除var。我试图让这个例子更加清晰,希望现在我的意思更明显。

编辑2:

此外,我已经查看了在Firebug中执行的脚本,他们肯定会将所有内容添加到var,该对象完全混乱。

2 个答案:

答案 0 :(得分:3)

是的,看起来不对。

MODULENAME = MODULENAME || {}; // missing var

var MODULENAME.SUBMODULENAME = (function() { // probably the missing var from above...
    var that = this;
    //add some stuff to that
    return that; // that is the WINDOW- wrong.
}());

DEMO可以造成的伤害:

var x = function() {
    alert('out');
}
var MODULENAME = MODULENAME || {};

MODULENAME.SUBMODULENAME = (function() {
    var that = this;
    that.x = function() {
        alert('DAMAGE');
    }
}());

x();​ // alert DAMAGE and not "out" - messed up with the global object!

答案 1 :(得分:0)

模块模式使用不正确,并且为什么不应该使用函数表达式的一个原因是它们的使用在函数声明中没有提供任何内容。如果打算创建全局函数(我怀疑它是),那么他们应该使用:

function somefuncion() {
  ...
}

如果他们的意图是将一个属性(在本例中是方法)添加到一个对象(更可能是这种情况),那么:

MODULENAME.SUBMODULENAME.somemethod = function() { /* do stuff */ };

如果需要有条件地创建方法,例如基于特征检测,以下可能适合:

(function(global, undefined) {

  // In here global is the global object
  global.MODULENAME = global.MODULENAME || {};
  global.MODULENAME.SUBMODULENAME = global.MODULENAME.SUBMODULENAME || {};

  // and undefined is undefined, belt and braces approach
  undefined = void 0;

  // Direct assignment
  function somemethod() {
      //do stuff      
  };

  // Assign directly to the "namespace" object
  MODULENAME.SUBMODULENAME.somemethod = somemethod;

  // Conditional assignment
  if ( sometest ) {
    MODULENAME.SUBMODULENAME.anothermethod = function(){...};

  // Try another way...
  } else if (someOtherTest) {
    MODULENAME.SUBMODULENAME.anothermethod = function(){...};

  // Default
  } else {
    MODULENAME.SUBMODULENAME.anothermethod = function(){...};
  }

  // Clean up 
  global = null;

}(this)); 

上面的一个问题是在外部函数内声明的每个函数都有一个关闭函数对象及其环境的闭包,因此它有点浪费资源。保持简单并且仅使用真正需要的模块模式并且只使用普通函数声明和分配而不是它更有效。不那么时髦但更实用。