8

最近、JS コードをリファクタリングしたところ、次のパターンに出くわしました。

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

これの利点は、 で定義されたすべてのものにアクセスできる関数を使用して非グローバル変数を作成することですAPP。、 などを入力せずに 、 、 bar にアクセスできAPP.fooます。 、などを使用してすべてにグローバルにアクセスすることもできます。それらをネストすることもできます。x, y, zAPP.bar()APP.xAPP.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にコンパイルするだけです。

速記が欲しいだけです。

たとえば、これは上記の 2 番目のコード ブロックにコンパイルされます。

//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 がもっと欲しいと思います。

4

2 に答える 2

1

あなたが調べたいと思うかもしれないこと:

将来利用可能になる可能性のあるEcmaScript6のモジュールシステムの提案もあります:http ://wiki.ecmascript.org/doku.php?id = harmony:modules

さて、目標がタイピングではなくタイピングである場合、foo()JavaScriptAPP.foo()の言語スーパーセットを作成するのは少し難しいと思います...

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
  }

})();
于 2012-07-14T23:45:27.457 に答える
0

あなたが説明しているのは、しばしば「モジュールパターン」と呼ばれるものです。「非表示」でアクセスできない内部メソッドと変数を定義できるので便利です。また、グローバル名前空間を汚染しません。詳細については、こちらを参照してください(これは、この手法に関する最初の記事の 1 つだと思います)

ただし、すべてを「公開」しているため、それほど役に立ちません。次のように実行できます (テスト コードが含まれています)。

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 ツールなど) も例として使用できると確信しています。

于 2012-07-14T18:53:38.920 に答える