使用jQuery创建一个简单的JavaScript类
我试图理解jQuery类,但进展不太顺利 我的目标是以这种方式使用课程(或学习更好的方法): 用其他人的例子,这就是我所尝试的:使用jQuery创建一个简单的JavaScript类,javascript,jquery,class,keyboard-events,Javascript,Jquery,Class,Keyboard Events,我试图理解jQuery类,但进展不太顺利 我的目标是以这种方式使用课程(或学习更好的方法): 用其他人的例子,这就是我所尝试的: $.Player = function ($) { }; $.Player.prototype.InitEvents = function () { $(this).keypress(function (e) { var key = e.which; if (key == 100) { MoveRi
$.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
左右移动
我有一种感觉,我对这个“班级”做了一些非常错误的事情
但我不知道为什么
(对不起我的英语)当您在
播放器
原型函数中使用此
时,此
指向当前播放器对象
但是当您使用$(this).keypress
时,它要求this
指向HTML元素
这两者根本不相容。只有一个this
,它指向当前播放器对象,而不是HTML元素
要解决您的问题,您需要在创建播放器对象时将HTML元素传递到播放器对象中,或者传递到相关的函数调用中
在构造时,可以将元素传递到播放器对象中,如下所示:
$.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
};
一个重要的问题是,您必须将传递的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实现之前没有),也没有方法(根据定义,这些方法只与类关联),而是提供类似于类的甜美语法的构造函数。TJ Crowder写了一篇关于JS“假”方法的精彩文章,虽然有点先进,但每个人都应该能从中学习到新的东西:此
在实例方法中引用实例对象本身,因此您不能使用$(此)。按键
,$(此)。css
等,因为此
不引用DOM元素或查询字符串。您的函数调用也是错误的,它应该读取this.MoveRight()
,但是由于您在jQuery处理程序中,该处理程序将this
上下文设置为DOM元素本身,您需要将实例的this
分配给作用域链中的一个级别较高的变量,以便您可以在处理程序中访问该变量,以调用其MoveRight
/MoveLeft
方法。您能告诉我如何更改代码来解决我提出的问题吗?如果我能把一个好的代码和我的相比,我会更容易看到我做了什么。(如果不太难的话)我可以试试看,但比起“修复”,它更接近于完全重写<代码>:P我来看看是否能举一个简单的例子。这是注释版本,很抱歉我的无知,但是我如何使用这个类?我的意思是,如果我用它,为什么我在问题中显示它不起作用。(如果不是很难)你能举个例子吗?(感谢您抽出时间回答我的问题)
(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();