如何创建一个小的Javascript扩展语言?

s12*_*ung 8 javascript closures namespaces coffeescript

我最近重构了我的JS代码并偶然发现了这种模式:

APP = (function() {
  var x,y,z;
  function foo() {}
  function bar() {}
  return {x:x, y:y, z:z, foo:foo: bar:bar};
})();
Run Code Online (Sandbox Code Playgroud)

这样做的好处是它创建了非全局变量,其中的函数可以访问定义的所有内容APP.所以APP.foo可以访问x, y, z,而无需打字吧APP.bar(),APP.x等一切都还可以与全球访问APP.bar(),APP.x等等.你也可以嵌套它们:

APP = (function() {
  var x,y,z;
  function foo() {}
  function bar() {}

  var WIDGETS = (function() {
    var a,b,c;
    function hello() {}
    function world() {}
    return {a:a, b:b, c:c, hello:hello, world:world};
  })();

  return {x:x, y:y, z:z, foo:foo: bar:bar, WIDGETS:WIDGETS};
})();
Run Code Online (Sandbox Code Playgroud)

因此WIDGETS可以访问变量APP,但反之亦然(APP.WIDGETS.hello可以使用foo(),但APP.foo必须使用WIDGETS.hello()).

我尝试使用ERB(我在Rails上)创建这个模式,但事实证明它很混乱.所以我正在考虑为此编写一个小的源到源编译器 - 像CoffeeScript(具有SASS的最小差异/扩展语言哲学),它只是将一些函数编译成替代的javascript.

我只想要一个速记.

例如,这将编译到我上面的第二个代码块:

//NAMESPACE is a magical function I compile down to the long version in the second code block
APP = NAMESPACE(function() {
  var x,y,z;
  function foo() {}
  function bar() {}

  var WIDGETS = NAMESPACE(function() {
    var a,b,c;
    function hello() {}
    function world() {}
    //**notice the missing return statement that I don't need to manage and map to my variables**
  });
  //**notice the missing return statement that I don't need to manage and map to my variables**
});
Run Code Online (Sandbox Code Playgroud)

简单和小 - 只是因此您​​不需要跟踪变量.还希望将命名空间分开(因此我可以将其拆分为多个文件):

APP = NAMESPACE(function() {
  var x,y,z;
  function foo() {}
  function bar() {}
  //**notice the missing return statement that I don't need to manage and map to my variables**
});
APP = NAMESPACE(function() {
  var WIDGETS = NAMESPACE(function() {
    var a,b,c;
    function hello() {}
    function world() {}
    //**notice the missing return statement that I don't need to manage and map to my variables**
  });
});
Run Code Online (Sandbox Code Playgroud)

有关如何做到这一点的任何想法?我不确定一切,但我认为如果存在,我会更喜欢Javascript.

Ric*_*asi 1

您可能想要研究的事情:

还有一个关于 EcmaScript 6 中的模块系统的提案,该提案将来可能会可用:http://wiki.ecmascript.org/doku.php ?id=harmony:modules

现在,如果目标只是打字foo()而不是APP.foo()那么我认为创建 javascript 的语言超集有点牵强......

如果您使用 CoffeeScript 导出变量就不会那么冗长:

APP = do ->
  [x,y,z] = []
  foo = ->
  bar = ->

  WIDGETS = do ->
    [a,b,c] = []
    hello = ->
    world = ->
    { a, b, c, hello, world }

  { x, y, z, foo, bar, WIDGETS }
Run Code Online (Sandbox Code Playgroud)

在实践中,您很少导出每个变量,事实上您将其中一些变量设置为“私有”。您还可以在对象本身内部定义函数:

APP = (function() {
  var x,y,z;

  var WIDGETS = (function() {
    var a,b,c;
    return {
      hello: function hello(){},
      world: function world(){}
    }

  })();

  return {
    foo: function foo(){},
    bar: function bar(){},
    widgets: WIDGETS
  }

})();
Run Code Online (Sandbox Code Playgroud)