module

気持ちPythonぽく。中身ははてなアンテナっぽく。

module = function(ns, impl) {
  new_module = update( namespace(ns), {
    NAME: ns
  }, impl );
  bindMethodsExceptClass( new_module );
  new_module.TYPE = "MODULE";
  return new_module;
}

usage:

module( "Data.Page", {
  foo: "foo in Data.Page module.",

  Pager: class( Object, {
    __init__: function(args) {
      this.foo = args.foo
    },

    hello: function() {
      alert( this.foo );
    }
  }),

  Navigation: class( Object, {
    __init__: function(args) {
      this.foo = args.foo; 
    },

    hello: function() {
      alert( this.foo );
    }
  }),

  hello: function() {
    alert( this.foo );
  }
});

pager = new Data.Page.Pager({foo:"FOO!!!"});
navi = new Data.Page.Navigation({foo: "navi."});
pager.hello();     // "FOO!!!"
navi.hello();      // "navi."
Data.Page.hello(); // "foo in Data.Page module."

関連関数は以下。

bindMethodsExcept = function(self, excepts) {
  var self_keys = except( keys(self), excepts );
  forEach( self_keys, function(k) {
    var func = self[k];
    if (typeof(func) == 'function') {
      self[k] = bind(func, self);
    }
  });
}

classFilter = function( obj, k ){
  var func = obj[k];
  if (func.hasOwnProperty('TYPE') && func.TYPE == 'CLASS')
    return 1;
};

findClass = function(obj) {
  return filter( partial(classFilter, obj), keys(obj) );
}

bindMethodsExceptClass = function(self) {
  var class_keys = findClass(self);
  bindMethodsExcept( self, class_keys );
}