【问题标题】:How to create a small Javascript extension language?如何创建一个小的 Javascript 扩展语言?
【发布时间】:2012-07-14 05:29:43
【问题描述】:

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

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

这样做的好处是它创建了非全局变量,函数可以访问APP 中定义的所有内容。所以APP.foo可以访问x, y, z和bar而不用输入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};
})();

所以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**
});

简单而小巧 - 这样您就无需跟踪变量。还想像这样分隔命名空间(这样我可以将其拆分为多个文件):

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**
  });
});

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

【问题讨论】:

  • 你可能会疯狂地尝试做这个。看看 Closure Compiler - 那里可能有一些重叠。
  • 嗯.. 似乎找不到类似的功能。不过感谢您的参考。
  • 附注如果有兴趣,请查看此页面上的答案以了解有关 CC 功能的更多信息。 stackoverflow.com/questions/11486022/what-is-closure-compiler
  • 是的,它似乎压缩,删除死代码和优化JS正确...?我正在尝试构建一种可以创建简写语法的东西(据我所知),它超越了 Javascript。
  • 您只是用内部变量来描述模块模式,我没有看到您使用的语法有任何特别的好处。

标签: javascript coffeescript namespaces closures


【解决方案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 }

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

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
  }

})();

【讨论】:

  • 感谢您的链接。 github 很棒。是的,这可能有点牵强……我想我不妨问问。我只想要更简洁的代码。认为这可能是最好的答案,所以我会批准。再次感谢。
【解决方案2】:

您所描述的是通常所说的“模块模式”。这很好,因为您可以定义“隐藏”且无法访问的内部方法和变量。它也不会污染全局命名空间。你可以阅读更多关于它的信息here(我相信这是关于该技术的第一篇文章。)还有here和here。

但是,由于您将所有内容都“公开”,因此它没有那么有用。你可以这样做(包括测试代码):

APP = function (me) {
      me.x = 0;
      me.y = 0;
      me.z = 0;
      me.foo = function () { alert(me.x); },
      me.bar = function () {};

      WIDGETS = function (me2) {
        me2.a = 0;
        me2.b = 0;
        me2.c = 0;
        me2.hello = function () {};
        me2.world = function () {};
        return me2;
      }({});

      return me;
   }({});

APP.x = 1;
APP.foo();

你可以用更少的语法得到同样的效果。

http://jsfiddle.net/ZwCUh/


作为旁注,有一些方法可以在没有编译器的情况下编写代码,通过原型让您接近您正在寻找的内容。一个很好的例子是 jQueryUI 的源代码。我确信其他库(原型、moo 工具等)也可以用作示例。

【讨论】:

  • 这不是有效的 JavaScript 语法。
  • 感谢您的链接。这很有帮助。它被称为“显示模块”模式。我想把事情公之于众。想我就足够了,改用“模块导出”模式——希望我能想到细微的差别。我提出的解决方案允许文件分离 - 会很好(我暂时不用它)
  • @CaseyChu - 是的 - 我隔开并举了一个完全错误的例子。我已经解决了这些问题。
  • 没关系。我尝试了“模块导出”模式,但它不一样。我已经在使用你的模式了,我只是不喜欢我需要一直输入 APP.WIDGETS.* 的事实——与其他语言相比感觉如此冗长——尤其是嵌套到 3 级时。
  • @user1090482 - 在js中总是可以做一个var shortcut = APP.WIDGETS;
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-13
  • 1970-01-01
相关资源
最近更新 更多