0

以前の js コードをより OOP スタイルに移行します。これがコードです。

function addEvent( obj, type, fn ) {
  if ( obj.attachEvent ) {
    obj['e'+type+fn] = fn;
    obj[type+fn] = function(){obj['e'+type+fn]( window.event );}
    obj.attachEvent( 'on'+type, obj[type+fn] );
  } else
    obj.addEventListener( type, fn, false );
}

function test() {

}

test.prototype = {
    init: function () {

        addEvent(document, 'mousedown', this.displaydown);

    },

    displaydown : function(e){
        document.getElementById('mydiv').innerHTML = "down";
        addEvent(document, 'mousemove', this.displaymove);
    },

    displaymove : function(e){
        document.getElementById('mydiv').innerHTML = "move";
    }
}

var test0 = new test();

test0.init()

mousedown の後に mousemove イベントを追加できませんでした

addEvent(document, 'mousemove', this.displaymove);

しかし、インラインスタイルを次のように書くと

addEvent(document, 'mousemove', function(e){
   document.getElementById('mydiv').innerHTML = "move";
});

大丈夫です。2つのコードが同じことをしているように見えます。なぜ違いがあるのですか?ありがとう!


編集、

2 泊の闘争の後、私は最終的に問題を解決しました。ジョンビー、教えてくれてありがとう。

このキーワードでエラーが発生します。オブジェクトの場合、これはオブジェクト自体ではなくウィンドウを参照します。解決策は、最初にグローバル パラメータme (me = this)を定義することです。今は大丈夫です。

4

1 に答える 1

2

これは、「this」キーがクロージャ内でスコープされる方法に関連する、古典的なJavascriptの障害です。説明する:

redPrinter = function() {
    this.X = 'red';
    return function() {
        return this.X;
    }
}

main = function() {
    this.X = 'blue';
    var myRedPrinter = new redPrinter();
    alert("Red printer returned: " + myRedPrinter());
}

main();

このコードは次のように出力されます。

Red printer returned: blue

次の行の「this」のスコープのため:

return this.X

実際には、呼び出し時にmain()オブジェクトに関連付けられています。

これに対処するには、一般的に2つの方法があります。

1) 関数クロージャ内で「this」キーワードを使用することは避けてください。この方法でコードを修正するには、すべてのイベントバインディングをカスケードするのではなく、1つの場所に収集するだけで、「displaydown()」と「displaymove()」の両方から「this」参照を削除します。

test.prototype = {
    init: function () {
        addEvent(document, 'mousedown', this.displaydown);
        addEvent(document, 'mousemove', this.displaymove);
    },

    displaydown : function(e){
        document.getElementById('mydiv').innerHTML = "down";
    },

    displaymove : function(e){
        document.getElementById('mydiv').innerHTML = "move";
    }
}

また

2) 関数カリー化を使用して、定義時にスコープをバインドします。説明のために、プロトタイプライブラリからbind()メソッドを削除しました。

// declare the global bind() method for all functions
Function.prototype.bind = function(obj) {
    var method = this,
    temp = function() {
        return method.apply(obj, arguments);
    };
    return temp;
} 

test.prototype = {
    init: function () {
        addEvent(document, 'mousedown', this.displaydown);
    },

    displaydown : function(e){
        document.getElementById('mydiv').innerHTML = "down";

        // note that we bind the method object here
        addEvent(document, 'mousemove', this.displaymove.bind(this));
    },

    displaymove : function(e){
        document.getElementById('mydiv').innerHTML = "move";
    }
}

ここでの重要な変更は次のとおりです。

this.displaymove.bind(this)

これは基本的に、「displaymove()を呼び出すときに、キーワード'this'を現在のEventオブジェクトではなく元のスコープコンテキストに再スコープします。

于 2009-05-05T05:14:45.300 に答える