Почему jQuery использует «new jQuery.fn.init ()» для создания объекта jQuery, но я не могу? - PullRequest
0 голосов
/ 07 декабря 2009

Я пытаюсь создать некоторый класс на основе стиля jQuery, например, следующий код.

myClass = window.myClass = function(x, y)
{
    return new myClass.fn.init(x, y);
};

myClass.fn = myClass.prototype = 
{
    init: function(x, y)
    {
        // logic for creating new myClass object.
    }
};

Я не понимаю, почему jQuery использует новое ключевое слово для создания своего класса, потому что из моего эксперимента JavaScript всегда создает объект myClass.init вместо объекта myClass. Однако я пытаюсь удалить новое ключевое слово в конструкторе myClass. Но это все равно не меняется. Можете ли вы объяснить, почему jQuery может это сделать, но я не могу или не могу дать мне код для использования в функции init?

Кстати, я могу использовать следующий код вместо кода стиля jQuery для создания того же объекта. Чем отличается мой код от кода JQuery? Есть ли польза от использования стиля jQuery?

myClass = window.myClass = function(x, y)
{
    this.init(x, y);
};

myClass.fn = myClass.prototype = 
{
    init: function(x, y)
    {
        this.x = x;
        this.y = y;
    }
};

PS. Мне нравится писать код, который разделяет исходную логику на функцию, потому что очень легко переопределить эту функцию другими людьми, которые используют мой код, как мой следующий код.

// override init function of myClass
myClass.fn._old_init = myClass.fn.init;
myClass.fn.init = function()
{
    // logic for doing something before init

    this._old_init();

    // logic for doing something after init
};

Спасибо

Ответы [ 3 ]

2 голосов
/ 07 декабря 2009

Этот подход должен работать отлично. Одна вещь, которую вы можете упустить, это тот факт, что с помощью этой техники вы не собираетесь создавать экземпляр myClass; вы собираетесь создать экземпляр myClass.prototype.init.

Таким образом, любые методы, определенные в myClass.prototype, не будут доступны для экземпляра. Вы хотите убедиться, что прототип init указывает на прототип myClass:

myClass.fn.init.prototype = myClass.fn;

FWIW, я не вижу никакой реальной выгоды в этом подходе. Что с этим не так? -

function myClass(x,y) {

    if ( !(this instanceof myClass) ) {
        return new myClass(x,y);
    }

    // Prepare instance

}

myClass.prototype = { /* Methods */ };

// It can still be overwritten:

var oldMyClass = myClass;

function myClass(x,y) {

    // Hack some stuff here...

    return new oldMyClass(x,y);
}
0 голосов
/ 07 декабря 2009

При инициализации объекта jQuery должен выглядеть следующий код.

jQuery = window.jQuery = window.$ = function (x, y)
{
    return new jQuery.fn.init(x, y);
};

jQuery.fn = jQuery.prototype = 
{
    init: function()
    {
        // some logic for object initialization
        return this;
    }
};

jQuery.fn.init.prototype = jQuery.fn;

Единственным преимуществом этого кода является то, что он всегда создает экземпляр объекта jQuery, хотя вы не используете ключевое слово new для создания объекта.

С другой стороны, мой код, использующий функцию init для объекта инициализации, не работает, если вы не используете ключевое слово new при вызове. Чтобы исправить это, вы должны добавить некоторый код, например, пример J-P, для проверки этого объекта. Если его тип не является текущим классом, он автоматически создаст для него экземпляр.

Оба кода должны работать нормально. Но мне нравится стиль jQuery больше, чем стиль "J-P", потому что его легко читать и изменять.

Спасибо

0 голосов
/ 07 декабря 2009

Я не совсем уверен, в чем вопрос, но я сделаю все возможное, чтобы ответить на то, что я думаю, вы спрашиваете.

ключевое слово new используется для создания экземпляра нового объекта, возвращаемого функцией, определенной свойством init в прототипе функции.

Я считаю, что код написан таким образом, что ключевое слово new не требуется каждый раз, когда вы создаете экземпляр нового объекта jQuery , а также делегируете логику, лежащую в основе конструкции объекта, прототипу. Первое, что я считаю, - сделать библиотеку чище для использования, а второе - сохранить логику инициализации в одном месте и позволить рекурсивно вызывать init для создания и возврата объекта, который правильно соответствует переданному аргументы.

Ваш второй блок кода не возвращает объект. Попробуйте в Firebug с

var myClass1 = myClass(1,2);
console.log(myClass1);

вы получаете this.init is not a function ошибку. Единственный способ, которым это будет работать, - это использовать ключевое слово new, как в

var myClass1 = new myClass(1,2);
console.log(myClass1);

Сравните это с кодом, похожим на код в jQuery

myClass = window.myClass = function(x, y)
{
    return new myClass.fn.init(x, y);
};

myClass.fn = myClass.prototype = 
{
    init: function(x, y)
    {
        this.x = x;
        this.y = y;
    }
};

var myClass1 = myClass(1,2);
console.log(myClass1);

var myClass2 = new myClass(1,2);
console.log(myClass2);

В каждом случае вы правильно получаете объект, возвращаемый со свойством x со значением 1 и со свойством y со значением 2, независимо от того, используется ключевое слово new или нет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...