【问题标题】:Creating a simple JavaScript class with jQuery使用 jQuery 创建一个简单的 JavaScript 类
【发布时间】:2013-01-19 19:50:15
【问题描述】:

我正在尝试理解 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
};

最终目标是使用键盘字母AD 让角色在屏幕上左右移动。

我觉得我在这个“类”上做错了什么 但我不知道为什么。

(对不起我的英语)

【问题讨论】:

  • this 在实例方法中引用实例对象本身,因此您不能使用 $(this).keypress$(this).css 等,因为 this 不引用 DOM 元素或查询字符串。您的函数调用也是错误的,它应该读取 this.MoveRight() 但由于您在将 this 上下文设置为 DOM 元素本身的 jQuery 处理程序中,您需要将实例的 this 分配给变量 a在范围链中升级,以便您可以在处理程序中访问它以调用其 MoveRight/MoveLeft 方法。
  • 你能告诉我你将如何改变我的代码来解决我提出的问题吗?如果我能比较好的代码和我的代码,我会更容易看到我做了什么。 (如果不是太难)
  • 我可以试试 man,但它比“修复”更接近完全重写。 :P我看看能不能做个简单的例子。
  • 这里是评论版本jsfiddle.net/gVhj8

标签: javascript jquery class keyboard-events


【解决方案1】:

一个重要的问题是您必须将传递的 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();

Fiddle

还要注意,JavaScript 没有实际的“类”(至少在 ES6 实现之前没有),也没有方法(根据定义,它们专门与类相关联),而是提供类似于类的甜美语法的构造函数。这是 TJ Crowder 写的一篇关于 JS 的“假”方法的很棒的文章,它有点高级,但每个人都应该能够从中学到新的东西:
http://blog.niftysnippets.org/2008/03/mythical-methods.html

【讨论】:

    【解决方案2】:

    当您在 Player 原型函数中使用 this 时,this 指向当前的 Player 对象。

    但是当您使用$(this).keypress 时,它要求this 指向一个HTML 元素。

    两者根本不相容。只有一个this,它指向当前的 Player 对象,而不是 HTML 元素。

    要解决您的问题,您需要在创建 Player 对象时将 HTML 元素传递到它或相关的函数调用中。

    您可以在构造时将元素传递给 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
    };
    

    【讨论】:

    • 抱歉我的无知,但是我如何使用这个类?我的意思是,如果我使用它,为什么我会在我的问题中显示它不起作用。 (如果不是那么难)你可以添加一个例子吗? (感谢您花时间回答我的问题)
    猜你喜欢
    • 2011-05-13
    • 2018-04-21
    • 1970-01-01
    • 2013-03-28
    • 2017-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-05
    相关资源
    最近更新 更多