4

次のコードで Dragger.prototype.wrap が必要な理由と、イベント処理メソッドを直接使用できない理由を理解しようとしています。

function Dragger(id) {
    this.isMouseDown = false;
    this.element = document.getElementById(id);
    this.element.onmousedown = this.wrap(this, "mouseDown");
}

Dragger.prototype.wrap = function(obj, method) {
    return function(event) {
        obj[method](event);
    }
}

Dragger.prototype.mouseDown = function(event) {
    this.oldMoveHandler = document.body.onmousemove;
    document.onmousemove = this.wrap(this, "mouseMove");
    this.oldUpHandler = document.body.onmousemove;
    document.onmouseup = this.wrap(this, "mouseUp");
    this.oldX = event.clientX;
    this.oldY = event.clientY;
    this.isMouseDown = true;
}

Dragger.prototype.mouseMove = function(event) {
    if (!this.isMouseDown) {
        return;
    }
    this.element.style.left = (this.element.offsetLeft
            + (event.clientX - this.oldX)) + "px";
    this.element.style.top = (this.element.offsetTop
            + (event.clientY - this.oldY)) + "px";
    this.oldX = event.clientX;
    this.oldY = event.clientY;
}

Dragger.prototype.mouseUp = function(event) {
    this.isMouseDown = false;
    document.onmousemove = this.oldMoveHandler;
    document.onmouseup = this.oldUpHandler;
}

それがないと変化するからだと言われたのですが、なぜ変化するのか、なぜラップ機能が変化を妨げているのか、ラップ機能がないと何が変わるのかthisわかりません。thisthis

4

2 に答える 2

8

関数がイベント ハンドラーとして使用される場合、キーワードはイベントをトリガーした DOM 要素を参照し、ラップしないとオブジェクトthisのインスタンス メンバーにアクセスできないため、それらをラップする必要があります。 Dragger、のようにthis.isMouseDown

例えば:

ボタンがあるとしましょう:

<input type="button" id="buttonId" value="Click me" />

そして、次のオブジェクトがあります。

var obj = {
  value: 'I am an object member',
  method: function () {
    alert(this.value);
  }
}

あなたが呼び出す場合:

obj.method();

valueオブジェクトのメンバーに含まれるテキストobj( 「私はオブジェクトのメンバーです」 )を含む警告が表示されます。

obj.method関数をイベント ハンドラーとして使用する場合:

document.getElementById('buttonId').onclick = obj.method;

ユーザーがボタンをクリックすると、「Click me」という警告が表示されます。

なんで?クリック イベントが発生すると、DOM 要素を指すキーワードobj.methodで実行され、ボタンにメンバーが含まれているため、 「クリックしてください」というアラートが表示されるためです。thisvalue

ここで実行されている上記のスニペットを確認できます。


コンテキストを強制するために、バインド関数を常に閉じておきます。

// The .bind method from Prototype.js
if (!Function.prototype.bind) {
  Function.prototype.bind = function(){
    var fn = this, args = Array.prototype.slice.call(arguments),
             object = args.shift();
    return function(){
      return fn.apply(object,
        args.concat(Array.prototype.slice.call(arguments)));
    };
  };
}

コンテキストを強制して、任意の関数をラップできます。最初の引数として、として使用されるオブジェクトを受け取り、this残りのオプションの引数は、ここでラップされた functionenter コードが呼び出されるものです。

ボタンの例では、次のように使用できます。

document.getElementById('buttonId').onclick = obj.method.bind(obj);

これは多くの状況で非常に役立ち、ECMAScript 5 の一部として導入される予定です。

于 2009-11-20T05:59:46.367 に答える
3

CMS はthis、さまざまなコンテキストでの価値について適切な回答を提供しました。ただし、補足として、ライブラリを使用していない場合、またはそのようなツールを持たないライブラリを使用している場合に、 Dragger.wrap( に似ている)の効果を一般化するために使用できる便利な関数を次に示します。dojo.hitch

var lockContext = function(context, callback) {
    return function() {
        callback.apply(context, arguments);
    }
};
于 2009-11-20T06:27:23.020 に答える