Dojo学習ノート(七):Making Funtions with hitch and partial


ドジョウbase/langは二つの有用な方法を含みます.lang.hitchとlang.partial.lang.hichは主にthis運転文脈を修正し、lang.partialは主に関数パラメータの個数を修正し、関数署名を行います.
1、JavaScriptにおける運行コンテキスト(execution contexts)
    JavaScriptでは、関数が呼び出されると、実行コンテキストが作成されます.コンテキストの作成は次の段階で行われます.
    (1)argmentsパラメータオブジェクトの作成;
    (2)関数作用ドメインscopeの作成;
    (3)関数における変数Varabelesの実装;
    (4)this属性(コンテキストcontext自体を指す)の作成.
    this属性はほとんどの開発者が紛らわしいところです.これは、実際には、関数の呼び出し時にコンテキストcontext(またはスコープscopeと呼ばれる)のオブジェクトの参照として、JavaScriptでは、関数実行時の実際のコンテキストは、関数が呼び出された時に決定されます.
    スコープはオブジェクトであり、メソッド関数として実行時の空間を呼び出すこともできるし、方法関数や属性などの定義空間としても利用できる.後は語法のスコープに言及します.これはJavaScriptの中で本当の役割領域であり、語法の作用領域にはクローズド技術のclosuresが使われていると考えられます. 
    関数呼び出し時のスコープは、JavaScriptで実行コンテキストと呼ばれます.
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>dojoConfig</title>
    <style type="text/css">
        .myNode {
            border: 1px solid #999;
            margin: 0.5em;
            padding: 0.5em;
            background-color: #ccc;
            float: left;
        }
    </style>
    <script src="dojo/dojo.js"></script>
    <script>
        // Retrieve the dependencies
        require(["dojo/query", "dojo/dom-construct", "dojo/domReady!"],
                function(query, domConstruct) {
                    function log(msg){
                        var c = document.getElementById("console");
                        if(!c){
                            c = domConstruct.create("div", {
                                id: "console"
                            }, document.body);
                        }
                        c.innerHTML += "<div>" + msg + "</div>";
                    }
                    var myObject = {
                        foo: "bar",
                        myHandler: function(evt){
                            //still contrived!
                            //  evt     :W3C   ,  evt.target, IE evt.srcElement
                            log("The value of foo is " + this.foo + ", from " + (evt && evt.target ? evt.target.id : window.event.srcElement.id));
                        }
                    };
                    var container = document.getElementById("nodeContainer");
                    for(var i=0; i<5; i++){
                        domConstruct.create("div", {
                            id: "node-" + (i+1),
                            className: "myNode",
                            innerHTML: "Fake button " + (i+1)
                        }, container);
                    }
                    query(".myNode").forEach(function(node){
                        node.onclick = myObject.myHandler;
                    });
                });
    </script>
</head>
<body>
<div id="nodeContainer">
</div>
</body>
</html>
出力結果:
The value of foo is undefined、from node-1
The value of foo is undefined、from node-2
The value of foo is undefined、from node-3
原因の分析:
    期待の結果は「The value of'foo'is bar」を表示することですが、私たちは情報を得ます.The value of'foo'is undefined.
    (1)node.onclick=myObject.myHandler
    ここでmyObject.myHandlerは解析を経て関数myHandlerになりました.関数だけです.myHandlerがmyObjectの方法であるという事実は完全に捨てられました.(myObject.myHandlerをOclickに割り当て、 contextは何のことですか?この関数がどこで定義されているかに関わらず、彼は完全にこの関数を対象自体から剥離しました.)
    (2)依然として迷っている場合は、JavaScriptでFunctions objectは他のオリジナルタイプと同じで、引用伝達ではなく、値伝達であることを覚えておく必要があります.上記の例では、私達はonclickにすぎません. myObject.myHandlerを直接指すように設定します.
    使用.applyと.call切り替え運転文脈execution contexts
query(".myNode").forEach(function(node){
      node.onclick = function(evt){
      myObject.myHandler.call(myObject,evt);
      };
});
    このようにバインディングイベントコードを修正すると、所望の結果が得られます.
(1)lang.hichバインディングを使ってコンテキストexecution contextを実行する
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>dojoConfig</title>
    <style type="text/css">
        .myNode {
            border: 1px solid #999;
            margin: 0.5em;
            padding: 0.5em;
            background-color: #ccc;
            float: left;
        }
    </style>
    <script src="dojo/dojo.js"></script>
    <script>
        // Retrieve the dependencies
        require(["dojo/_base/lang","dojo/query", "dojo/dom-construct", "dojo/domReady!"],
                function(lang,query, domConstruct) {
                    function log(msg){
                        var c = document.getElementById("console");
                        if(!c){
                            c = domConstruct.create("div", {
                                id: "console"
                            }, document.body);
                        }
                        c.innerHTML += "<div>" + msg + "</div>";
                    }
                    var myObject = {
                        foo: "bar",
                        myHandler: function(evt){
                            //still contrived!
                            log("The value of foo is " + this.foo + ", from " + (evt && evt.target ? evt.target.id : window.event.srcElement.id));
                        }
                    };
                    var container = document.getElementById("nodeContainer");
                    for(var i=0; i<5; i++){
                        domConstruct.create("div", {
                            id: "node-" + (i+1),
                            className: "myNode",
                            innerHTML: "Fake button " + (i+1)
                        }, container);
                    }
                    query(".myNode").forEach(function(node){
                        node.onclick = lang.hitch(myObject, myObject.myHandler);
                    });
                });
    </script>
</head>
<body>
<div id="nodeContainer">
</div>
</body>
</html>
説明:
lang.hichは関数のコンテキスト、キーコードを指定できます.
query(".myNode").forEach(function(node){
     node.onclick = lang.hitch(myObject, myObject.myHandler);
});
(2)パラメータオブジェクトThe argments oject
    argments objectは本物のJavaScriptのAray objectではありません.いくつかの態様は、配列と類似しているが(例えば、数字の下付き索引を用いて、length属性などを含む)、読み取り専用であるため、いくつかのAray方法は、それを無効にする(Aray.prototype.slice).
(3)lang.partialを使用して関数を修正してfunction signatureに署名する.
query(".myNode").forEach(function(node){
     //don't forget: method first, fixed arguments second!
     node.onclick = lang.partial(myObject.myHandler, myObject);
});
 (4)hichとpartialの長所を統合する
    httichのメリット(強制運転コンテキスト)とpartialのメリット(事前パラメータ)を合わせたいですか?はい、lang.hitchはさらに強化して、以上の二つの仕事を完成できます.contextとmethodの二つのパラメータを追加して、任意の数のパラメータを追加してください.lang.hitchはコンテキストを結合し、事前パラメータを設定して、新しい関数を生成します.
    備考:hich 和 partialは関数式プログラミングへの入り口です. functional programming);Dojo Toolkit はい、 dojox/lang/functional には多くの関数式プログラミング技術が提供されています.暇があれば見てください.
この記事は「IT技術学習と交流」ブログからの転載をお断りします.