12

jQuery クラスを理解しようとしていますが、うまくいきません。

私の目標は、クラスをこのように使用することです(または、より良い方法を学ぶことです):

var player = new Player($("playerElement"));
player.InitEvents();

他の人の例を使用して、これは私が試したことです:

$.Player = function ($) {

};

$.Player.prototype.InitEvents = function () {

    $(this).keypress(function (e) {
        var key = e.which;
        if (key == 100) {
            MoveRight();
        }
        if (key == 97) {
            MoveLeft();
        }
    });
};

$.Player.prototype.MoveRight = function () {
    $(this).css("right", this.playerX += 10);
}

$.Player.prototype.MoveLeft = function () {
    $(this).css("right", this.playerX -= 10);
}

$.Player.defaultOptions = {
    playerX: 0,
    playerY: 0
};

A最終的な目標は、キーボードの文字とを使用して、画面上でキャラクターを左右に移動させることDです。

この「クラス」で何か非常に悪いことをしているように感じますが、その理由はわかりません。

(私の英語でごめんなさい)

4

2 に答える 2

23

重要な問題は、渡された jQuery オブジェクト/要素を 1this.elementつまたは別の要素に割り当てて、this.propertyName後でインスタンスのメソッド内でアクセスできるようにする必要があることです。

これらの関数はスコープチェーンではなく、インスタンスのコンストラクターのプロトタイプで定義されているため、MoveRight()/をそのように直接呼び出すこともできません。したがって、これらを呼び出すにはインスタンス自体への参照が必要です。MoveLeft()

以下のコードを更新してコメントしました。

(function ($) { //an IIFE so safely alias jQuery to $
    $.Player = function (element) { //renamed arg for readability

        //stores the passed element as a property of the created instance.
        //This way we can access it later
        this.element = (element instanceof $) ? element : $(element);
        //instanceof is an extremely simple method to handle passed jQuery objects,
        //DOM elements and selector strings.
        //This one doesn't check if the passed element is valid
        //nor if a passed selector string matches any elements.
    };

    //assigning an object literal to the prototype is a shorter syntax
    //than assigning one property at a time
    $.Player.prototype = {
        InitEvents: function () {
            //`this` references the instance object inside of an instace's method,
            //however `this` is set to reference a DOM element inside jQuery event
            //handler functions' scope. So we take advantage of JS's lexical scope
            //and assign the `this` reference to another variable that we can access
            //inside the jQuery handlers
            var that = this;
            //I'm using `document` instead of `this` so it will catch arrow keys
            //on the whole document and not just when the element is focused.
            //Also, Firefox doesn't fire the keypress event for non-printable
            //characters so we use a keydown handler
            $(document).keydown(function (e) {
                var key = e.which;
                if (key == 39) {
                    that.moveRight();
                } else if (key == 37) {
                    that.moveLeft();
                }
            });

            this.element.css({
                //either absolute or relative position is necessary 
                //for the `left` property to have effect
                position: 'absolute',
                left: $.Player.defaultOptions.playerX
            });
        },
        //renamed your method to start with lowercase, convention is to use
        //Capitalized names for instanceables only
        moveRight: function () {
            this.element.css("left", '+=' + 10);
        },
        moveLeft: function () {
            this.element.css("left", '-=' + 10);
        }
    };


    $.Player.defaultOptions = {
        playerX: 0,
        playerY: 0
    };

}(jQuery));

//so you can use it as:
var player = new $.Player($("#playerElement"));
player.InitEvents();

フィドル

また、JavaScript には実際の「クラス」 (少なくとも ES6 が実装されるまで) もメソッド (定義上、クラスにのみ関連付けられている) もありませんが、クラスに似た甘い構文を提供するコンストラクターはありません。JS の「偽の」メソッドに関して TJ Crowder が書いた素晴らしい記事を次に示します。これは少し高度ですが、誰もがそれを読むことで何か新しいことを学べるはずです:
http://blog.niftysnippets.org/2008/03/mythical-methods .html

于 2013-01-19T21:04:21.160 に答える
6

プロトタイプ関数this内で使用する場合、現在の Player オブジェクトを指します。Playerthis

ただし、使用する場合は、HTML 要素を指す$(this).keypress必要があります。this

2つは単に互換性がありません。1 つだけありthis、HTML 要素ではなく、現在の Player オブジェクトを指します。

問題を解決するには、作成時に HTML 要素を Player オブジェクトに渡すか、関連する関数呼び出しに渡す必要があります。

次のように、構築時に要素を Player オブジェクトに渡すことができます。

$.Player = function ($, element) {
        this.element = element;

};

$.Player.prototype.InitEvents = function () {

    $(this.element).keypress(function (e) {
        var key = e.which;
        if (key == 100) {
            MoveRight();
        }
        if (key == 97) {
            MoveLeft();
        }
    });
 };

 $.Player.prototype.MoveRight = function () {
     $(this.element).css("right", this.playerX += 10);
 }

 $.Player.prototype.MoveLeft = function () {
     $(this.element).css("right", this.playerX -= 10);
 }

$.Player.defaultOptions = {
    playerX: 0,
    playerY: 0
};
于 2013-01-19T20:27:32.830 に答える