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
を使用して画面上でキャラクターを左右に移動させることです。
私はこの「クラス」で何か間違ったことをしているように感じますが、理由はわかりません。
(私の英語で申し訳ありません)
重要な問題は、渡されたjQueryオブジェクト/要素を_this.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
this
プロトタイプ関数内でPlayer
を使用する場合、this
は現在のPlayerオブジェクトを指します。
ただし、$(this).keypress
を使用する場合、this
がHTML要素を指す必要があります。
2つは単に互換性がありません。 this
は1つだけで、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
};