4

コードをモジュール化するために、次のクロージャ パターンを使用しています。

(function(root) {
  // MODULE CODE HERE

  if (typeof module !== 'undefined' && module.exports) { // CommonJS 
    /* var dependencies = require(...) */
    module.exports = myModule;
  } else if (typeof define !== 'undefined' && define.amd) { // AMD
    /* var dependencies...; */
    define([/* dependencies */], function(/* dependencies */) {
      /* Assign closure level vars to respective arguments */
      return myModule;
    });
  } else {
    // Dependencies??
    root.myModule = myModule;
  }
})(this);

つまり、機能検出を使用して、CommonJS モジュール (node.js など)、AMD、または基本的なグローバル名前空間のインスタンス化をサポートします。

これは node.js で正常に機能します。私はまだそれを読んでいるので、AMD パターンをまだテストしていません(編集 2 を参照してください: AMD はまったく同じ効果を示します)。ただし、モジュールに依存関係がある場合、ブラウザーでは失敗します。つまり、たとえばmyModule、別のモジュールで定義されているものを参照する場合: たとえば、上記のようにsuper.jschild.jsそれぞれのモジュール定義を使用して、 (ブラウザーで)super.jsという関数を作成するとします。のようなものを取得します。root.superroot === windowchild.jssuper()super is not a function

何が起きてる?

それを修正するために、要素に読み込まれるsuper.jsとの順序を変更しました。次に、jQuery を使用して、ドキュメントの準備ができたら強制的にロードしようとしました。child.js<script>child.js

$(document).ready(function() {
  $.getScript('child.js', function() {
    // Do stuff with child, which calls super
  });
});

...再び、同じ問題。ただし、どちらの場合も、コンソールに入ると、super期待どおりに利用可能で定義されています。

おそらく異なる(つまり、グローバルではない)スコープからのものsuperであると思われるのはなぜですか?child.js


CommonJS エクスポートで依存性注入ビットを削除すると、node.js で同じエラーが発生して失敗します (依存性がある場合)。


EDIT @Amberlampsの回答で問題は解決しましたが、なぜこれが発生するのかという質問には回答しませんでした。私のモジュールパターンは次のとおりです。

(function(root) {
  // MODULE CODE HERE

  if (typeof module !== 'undefined' && module.exports) { // CommonJS 
    /* var dependencies = require(...) */
    module.exports = myModule;
  } else if (typeof define !== 'undefined' && define.amd) { // AMD
    /* var dependencies...; */
    define([/* dependencies */], function(/* dependencies */) {
      /* Assign closure level vars to respective arguments */
      return myModule;
    });
  } else {
    if (root.hasOwnProperty(/* dependencies */)) {
      /* var dependencies = root... */
      root.myModule = myModule;
    }
  }
})(this);

これにより、環境間で依存関係が共通の名前で保持されます。ただし、疑問が残ります。グローバル オブジェクトがクロージャのスコープ内で使用できないのはなぜですか?


EDIT 2私は RequireJS と AMD を試していて、AMD が機能するように上記のコードを修正しました。この場合もまったく同じことが起こります。グローバルオブジェクトをクロージャー内で使用できるようにするには、クロージャー内の変数に明示的に割り当てる必要があります...

4

1 に答える 1

2

このパターンは問題なく動作します。と呼ばれる関数で実際にテストし、super経由で呼び出すと、 は予約語super()であるため、エラーが発生する可能性があります。次のコードは正常に動作します。super

(function(root) {

    root.super = function() {

        console.log("hello");

    };

}) (window);

(function(root) {

    root.super();

}) (window);

を使用して関数を呼び出すことができますwindow.super()super()ただし、エラーになります。

于 2013-01-17T15:20:52.933 に答える