JavascriptのFunctionコンストラクタでコンテキストby Ben Nadelを偽造

5711 ワード


私のjQueryテンプレートタグ言語(JTML)プロジェクトでは、JTMLテンプレートをJS関数にコンパイルする方法が必要です.これにより、いつでも新しいHTMLタグに変換できます.ただし、JTMLコードは非アクティブドメイン(グローバル)変数に関連しており、関数の実行時にレンダリングエンジンのコンテキストで使用できるため、厳しい問題です.このプロジェクトのコードを作成するときに考えられる唯一の方法は、テンプレートがレンダリングされる必要があるときに新しいFunction()を作成することです.これにより、レンダリングエンジンを事前にコンパイルする目的にある程度反します.熟考した結果、JSのapply()機能で動的な役割ドメインを作成し、関数をプリコンパイルできるかどうか考えています.
 
apply()またはcall()メソッドを使用して関数の実行コンテキストを変更すると、実際には「this」の参照を変更します.これは非アクティブドメインでは効果はありませんが、関数の閉パケットチェーンに登ってthis(グローバルオブジェクト)が見つかります.しかし、このような関数があれば、実行が完了する前に自分のthisコンテキストをチェックすることができますか?関数を作成し、その関数が実行される前に「this役割ドメイン」変数をローカル役割ドメインに挿入すると、関数のコンテキストを変更することで、使用可能な非役割ドメイン変数を簡単に動的に変更できるはずです.次のdemoは私が言います.
<!DOCTYPE HTML>

<html>

<head>

    <title>Javascript Function() With Context</title>

    <script type="text/javascript" src="jquery-1.4.2.js"></script>

    <script type="text/javascript">



        // I am a proxy for the Function() constructor that prepends

        // code to copy the function's context variables into the

        // function local scope so that they may dynamically changed

        // at the time of execution.

        // Function     。                             。

        function FunctionContext( sourceCode ){



// Call and return the Function() constructor. Notice

// that if the THIS is not Window, we are VAR'ing the

// context variables into the function local scope.

            return(Function(

                    "if (this != window){" +

                            "for (var __i in this ){" +

                            "eval( 'var ' + __i + ' = this[ __i ];' );" +

                            "}" +

                            "}" +

                            sourceCode

            ));

        }





        // -------------------------------------------------- //

        // -------------------------------------------------- //





        // Define a function that uses a variable that is not

        // defined as part of the function source code.

        var saySomething = FunctionContext(

                "console.log( name + ', you\\\'re looking so hot!' );"

        );





        // -------------------------------------------------- //

        // -------------------------------------------------- //





        // Now, execute the saySomething() method in three different

        // contexts, each of which changes the name.

        saySomething.apply({

            name: "Tricia"

        });



        saySomething.apply({

            name: "Vicky"

        });



        saySomething.apply({

            name: "Erika"

        });



    </script>

</head>

<body>

<!--- Intentionally left blank. --->

</body>

</html>

私はこの関数FunctionContext()を作成しました.実質的にはJSのFunction()コンストラクタエージェントです.コードブロックがFunctionコンストラクタパラメータに入力される前に、ヘッダに論理を挿入する作業です.この論理検査関数の「this」コンテキストです.関数のコンテキストがwindowオブジェクトでない場合は、call()またはapply()メソッドで書き換えられていることを示し、すべてのthis役割ドメイン値が関数ローカル役割ドメインの変数にコンパイルされます.任意のコンテキストの変数は、関数内部論理では非役割ドメイン値として使用できます.
 
上のコードを走ると、出力:
Tricia, you're looking so hot!Vicky, you're looking so hot!Erika, you're looking so hot!
 
 
ご覧のようにapply()を使用することで、コンパイル後の関数を実行するたびにコンテキストを変更します.また、レプリケーションが初めて実行されてから「this」「役割ドメイン変数をローカル役割ドメインに適用し、変数には適用されません」name「エラーは報告されません.
 
関数が実行されると、変数を動的に使用可能に変更する方法が必要です.eval()関数だけを使用すると、プリコンパイルの利点が失われます.Function()コンストラクタのみを使用する場合は、既存のパラメータを使用していない場合に使用可能な変数に変更する方法が考えられません(どのように繰り上げるかさえ分からないかもしれません).2つの組み合わせで使用することで,最も優雅な方法で利用可能な局所変数に変換することを見出した.
 
原文:http://www.bennadel.com/blog/1927-Faking-Context-In-Javascript-s-Function-Constructor.htm