5

誰かが私にこれを説明できますか?

var diagramImage = new Kinetic.Shape(function () {
    var context = this.getContext();
    context.beginPath();
    context.lineWidth = 1;
    //This is crazy tricks. It's part of the KineticJS demo website, but how am I able to assign diagramImage.color here?
    context.strokeStyle = diagramImage.color;

    var lastVertice = polygon.Vertices[polygon.Vertices.length - 1];

    context.moveTo(lastVertice.X, lastVertice.Y);

    for (var i = 0; i < polygon.Vertices.length; i++) {
        var vertice = polygon.Vertices[i];
        context.lineTo(vertice.X, vertice.Y);
    }

    context.stroke();
    context.closePath();
});

diagramImageKineticコンストラクターが戻るまで存在しないように思えますが、作成される前に、コンテキストをの色に割り当てることができます(そして、そうする必要があるようですstrokeStylediagramImagediagramImageなぜこれが機能するのですか?

編集:完全なコード:

function DrawPolygon(diagramLayer, polygon) {
    var diagramImage = new Kinetic.Shape(function () {
        var context = this.getContext();
        context.beginPath();
        context.lineWidth = 2;
        //This is crazy tricks. It's part of the KineticJS demo website, but how am I able to assign diagramImage.color here?
        context.strokeStyle = diagramImage.color;

        var lastVertice = polygon.Vertices[polygon.Vertices.length - 1];

        context.moveTo(lastVertice.X, lastVertice.Y);

        for (var i = 0; i < polygon.Vertices.length; i++) {
            var vertice = polygon.Vertices[i];
            context.lineTo(vertice.X, vertice.Y);
        }

        context.stroke();
        context.closePath();
    });

    diagramImage.color = "red";

    diagramImage.on("mouseover", function () {
        this.color = "green";
        diagramLayer.draw();
    });

    diagramImage.on("mouseout", function () {
        this.color = "red";
        diagramLayer.draw();
    });

    diagramLayer.add(diagramImage);
    planViewStage.add(diagramLayer);
}
4

3 に答える 3

8

呼び出している場所はdiagramImage.color、コンストラクターに渡されるクロージャー/関数内にあるためKinetic.Shapeです。この関数は呼び出されません/コンストラクターによって作成された新しいインスタンスがに割り当てられるまで、コンストラクターによって実行されませんdiagramImage

何が起こっているのかをよりよく説明できる最小限の例を次に示します。

var MyObject = function(f){
  this.myFunc = f; // f is executed sometime later...
};
MyObject.prototype.execute = function(){
  this.myFunc();
};

var myObjInst = new MyObject(function(){
  console.log("myObjInst:", myObjInst);
});
myObjInst.execute();

Twisolが指摘したように、これはthis代わりに使用することで改善できます。例えば:

(function(){
  var MyObject = function(f){
    this.myFunc = f; // f is executed sometime later...
  };
  MyObject.prototype.execute = function(){
    this.myFunc();
  };

  var myObjInst = new MyObject(function(){
    console.log("myObjInst:", this);
  });
  myObjInst.execute();
})();

ただし、Chrisが指摘したように、APIで文書化されていない限り、コールバック中にthis参照される保証はありません。したがって、ここで引き続き使用する方が、これら2つのオプションの方が優れている可能性があります。Kinetic.ShapediagramImage

要するに、これはJavaScriptの最良のAPI/例/使用法ではないと思います-そして私はこれをあなたが扱わなければならないJavaScriptのニュアンスとは考えません。確かに、これらのニュアンスは必要に応じて存在しますが、必ずしもそうする必要はありません。

于 2012-02-14T17:04:41.703 に答える
1

これは興味深い構成です。何が起こっているようです:

  • diagramImage宣言によって何かが割り当てられる前の参照です。これを視覚化するためvar diagramImageに、それが前の行にそれ自体であったと想像してください。
  • Kinetic.Shape後で使用するコンストラクター引数の1つとして、その無名関数であるコールバックを受け取ります。
  • コールバックはKinetic.Shapeオブジェクトを参照しようとしています。thisおそらく、後で(使用によって明らかにされるように)何を参照するかを説明するいくつかの契約がありthis.getContext()、それはKinetic.Shape目的ではありません。
  • diagramImageは参照であり、参照が使用されるまでに、新しいものが割り当てられているためKinetic.Shape、上記の目的で使用するのはコーシャです。

原則として、これは、ローカル変数を使用して現在のこれをコールバックで使用できるようにする通常のパターンと同じです。

var self = this;
$('myelement').click( function(){ self.hi = true; } );

ここでは、後で使用できるようになる変数は現在のオブジェクトではなく、そのオブジェクトのメンバーです。

于 2012-02-14T17:50:26.360 に答える
0

この投稿はそれを説明するのに役立つと思います-http://www.quirksmode.org/js/associative.html

特に連想配列のセクション。書き込みでは、JavaScriptのオブジェクトも連想配列と見なされると説明されています。

したがって、イベントdiagramImage.strokeStyleは明示的に定義されていない可能性がありますが、それでも参照できますdiagramImage['strokeStyle']

それは役に立ちますか?

于 2012-02-14T17:06:52.470 に答える