2

以下は、いくつかの複雑な依存関係があるプロジェクトで使用しているコードです。すべての依存関係がロードされていることを確認した後、以下に示すonReadyCallback()を起動します。2つの質問があります:

  1. 匿名ハンドラーのapplyメソッドであるanonymousHandler.apply(MyNameSpace)を使用して、Document.readyを呼び出すのは正しいですか。
  2. 私が理解していることから、私はapplyメソッドを使用しているため、ドキュメントの準備完了状態に関係なく、匿名関数がすぐに起動します。次に、MyNameSpaceのコンテキストをanonymousHandlerに渡して、関数内の「this」がMyNameSpaceを参照するようにするにはどうすればよいですか。

    var onReadyCallback = function(){
        jQuery(document).ready(function(){
           if(!this.loggedIn()){
              return;
           }
           ...Lots of Code referring to MyNameSpace using "this"
    
        }.apply(MyNameSpace));
    };
    
    //load the additional files that are needed and fire onReadyCallback
    MyNameSpace.Util.loadFiles(defaultJsFiles,function(){ 
        MyNameSpace.Util.require(['My.App','My.Theme','My.DomHandler'], function(){
           onReadyCallback.apply(window);          
        });
    });
    
4

2 に答える 2

4

匿名関数と を使用して、これはどうcallですか?

jQuery(document).ready(function() {
    (function() {
        // this == MyNamespace
    }).call(MyNamespace);
});
于 2011-06-08T16:31:03.003 に答える
1

通常、readyイベントjQuery関数はこのように呼び出されます

$(function() { /* ... */ });
// or 
jQuery(function() { /* ... */ });
// or
jQuery(document).ready(function() { /* ... */ });

要するに、関数には特定のコンテキストが与えられていません。jQuery によって関数に与えられる実際のコンテキストHTMLDocumentは、引数に関係なく要素です (最後の例ではdocument)。なぜこれがそうなのかは別の問題です。

通常、これらの各関数は、すべてがロードされた後に呼び出されますが、必ずしもそうではありません。あなたの場合、イベントが発生するMyNameSpace前に参照があります。readyJavascript がLALRタイプの言語であり、宣言されたシンボルが後で見つかる場合でも、これは良い習慣ではありません。MyNameSpacejQuery がreadyコールバック関数をトリガーする前に、後で別の値に設定するとどうなるでしょうか? readyコールバックはその新しい参照を取得しません。意図的でない限り、すべての準備が整ったら、コールバック内で参照を行う必要があります。ready

次に、readyコールバック内で、コンテキストを関数に割り当てる他の手法があります。lonesomedayは、あなたがやろうとしていることを達成するための正しい方法をほとんど与えてくれました。

(function() {
    // this == MyNamespace
}).call(MyNamespace);

上記のコードは、無名関数をすぐに実行します。this == MyNameSpace

注: applycallの違いについては、こちらで説明しています

さて、あなたが提供したコードの下部が来ます:

//load the additional files that are needed and fire onReadyCallback
MyNameSpace.Util.loadFiles(defaultJsFiles,function(){ 
    MyNameSpace.Util.require(['My.App','My.Theme','My.DomHandler'], function(){
       onReadyCallback.apply(window);          
    });
});

これは問題があり、不要です。関数onReadyCallbackはそこでのみ必要ですか、それとも数回呼び出されますか? 一度だけ呼び出す必要がある場合は、グローバル名前空間を省いて、次のようにします。

//load the additional files that are needed and fire onReadyCallback
MyNameSpace.Util.loadFiles(defaultJsFiles,function(){ 
    MyNameSpace.Util.require(['My.App','My.Theme','My.DomHandler'], function(){

       // if everything is done loading, the function will be executed, otherwise
       // it's execution will be postponed later
       jQuery(function() {

           // create our nicely wrapped anonymous function now
           (function() {
              if(!this.loggedIn()){
                 return;
              }
              // ...Lots of Code referring to MyNameSpace using "this"

           })(MyNameSpace);  // grab our most recent reference of `MyNameSpace`

       });
    });
});

インデントが気に入らない場合 (開発者の好みにすぎません)、readyコールバック内のすべてを (something like)に置き換えます。

 initMyNameSpace.apply(MyNameSpace);

グローバル空間の外側に関数を作成します。

 function initMyNameSpace() {
    if(!this.loggedIn()){
       return;
    }
    // ...Lots of Code referring to MyNameSpace using "this"

 };

しかし、少なくともrequireコールバック関数に入れることをお勧めします...

  1. ...一度だけ実行される関数でグローバル名前空間を汚染しません
  2. ...どこからでもアクセスできません (非公開にしてください)
  3. ...ソースコードを編集するときにすぐに見つけることができます

: 通常、applycallは、 または のようなオブジェクトに繰り返しアクセスすることを避けるために使用されますsome.thing.pretty.deep = value;。1 つの関数を多くのオブジェクトに適用する必要があるが、すべてのオブジェクトに適用する必要がないため、オブジェクトのプロトタイプを拡張することはお勧めできません。

とにかくこれは私の意見であり、あなたのコードやあなたが何をしているのかについての知識がなくても、私はどのように物事を行うでしょうか。

于 2011-06-08T17:41:22.063 に答える