Запись OO Javascript с помощью jQuery

Я исхожу из фона прототипа JS, где OO Javascript рекомендуется с помощью Class.create(). Теперь я выполняю некоторую работу JQuery, и я пытаюсь написать правильно структурированный код JQuery, где я могу, например, вызвать одну и ту же функцию объекта из двух разных обработчиков событий кликов.

Вот код в Prototype:

document.observe("dom:loaded", function() {

    // create document
    APP.pageHelper = new APP.PageHelper();


});

// namespace our code
window.APP = {};

// my class
APP.PageHelper = Class.create({

  // automatically called
  initialize: function(name, sound) {
    this.myValue = "Foo";

    // attach event handlers, binding to 'this' object
    $("myButton").observe("click", this.displayMessage.bind(this))

  },

  displayMessage: function() {
    console.log("My value: " + this.myValue); // 'this' is the object not the clicked button!
  }

});

Мне интересно, как следующий код может быть реплицирован в JQuery, где невозможно связать вызов функции с объектом, в котором он вызван, а 'this' - это всегда щелчок элемента.

Я слышал о том, как сделать это модулем "Модуль" Дугласа Крокфорда (http://www.yuiblog.com/blog/2007/06/12/module-pattern/), но я бы с удовольствием, если бы кто-то мог покажите мне, как реализовать код выше, используя JQuery и этот шаблон.

Спасибо заранее.

Ответы

Ответ 1

Вы можете абсолютно привязать событие к чему-то другому, кроме элемента dom. Просто используйте $.proxy.

Описание:

Принимает функцию и возвращает новую, которая всегда будет иметь определенный контекст. версия добавлена: 1.4

 /**
  * @param function - The function whose context will be changed.
  * @param context - The object to which the context (this) of the function should be set.
  */
jQuery.proxy( function, context )

Этот метод наиболее полезен для привязки обработчиков событий к элементу, где контекст обращается к другому объекту. Кроме того, jQuery гарантирует, что даже если вы привяжете функцию, возвращенную из jQuery.proxy(), она все равно отменит правильную функцию, если передала оригинал.

Ответ 2

Я откатываю свои собственные объекты на основе этой хорошей статьи:

http://www.klauskomenda.com/code/javascript-programming-patterns/

Я просто выбираю, какой шаблон имеет смысл для проекта, над которым я работаю. Так что, например, быстрый пример того, что вы просите, будет следующим:

$.myNamespace.myClass = function (options) {
    this.settings = $.extend({ ... defaults ... }, options);
    this.init();
};
$.myNamespace.myClass.prototype.settings = {
    someValue: 'default',
    someSelector: '#myButton'
};
$.myNamespace.myClass.prototype.init = function () {
    var self = this;
    $(self.settings.someSelector).click(function (event) {
        console.log(self.settings.someValue);
    });
};

Вы ответили ниже, что знаете о прототипе, но синтаксис немного раздражает. Я думаю, что это просто вопрос использования одного синтаксиса над другим. Я уверен, что в библиотеке Prototype используются блокировки и .prototype, как и выше, и, как и некоторые другие ответы ниже. В конце концов, просто напишите синтаксис, с которым вам комфортно. Предложение использовать кофе Script тоже круто - все, что плавает на вашей лодке:)

Ответ 3

Вам не нужно Class.create() писать классы в javascript.

APP.PageHelper = function(name, sound) { // this is the constructor
    this.myValue = "Foo";
    // attach event handlers, binding to 'this' object
    $('#myButton').click($.proxy(this.displayMessage, this)); // use $.proxy instead of `bind`
}
APP.PageHelper.prototype = { // define more prototype functions here
    displayMessage: function() {
        console.log("My value: " + this.myValue); // 'this' is the object not the clicked button!
    }
};

Теперь для более сложных классов с наследованием я использую John Resig простое наследование класса.

Я также разделяю классы на файлы, завернутые с закрытием. Это будет PageHelper.js:

;!!window['APP'] && (function (NS, $) {
    NS.PageHelper = Class.extend({ // see link above
        // functions
        init: function () { // constructor

        },
        displayMessage: function() { 

        }
    });
})(window['APP'], jQuery);

Ответ 4

Если вы ищете несколько схожую структуру ООП для JQuery, вы можете попробовать http://code.google.com/p/jquery-klass/

Это то, что я использую.

Ответ 6

Я думаю, что лучшая реализация класса jQuery принадлежит блогу Джона Ресига (http://ejohn.org/blog/simple-javascript-inheritance/). Я очень рекомендую это; он очень похож на Prototype JS.

Я написал библиотеку поверх нее, чтобы упростить дизайн OO внутри jQuery (https://github.com/arturnt/brickjs). Например, чтобы делать то, что вы делаете, вы можете сделать следующее.


Comp.APP = {};
Comp.APP.PageHelper = Comp.extend({
    init: function(e) {
        this._super(e);
        this.myValue = "foo";
    },
    "#myButton click": function() {
        console.log(this.myValue); //prints
    }
});