为什么jQuery使用“new jQuery.fn.init()”来创建jQuery对象,但我不能?

时间:2009-12-06 22:40:12

标签: javascript jquery oop

我尝试创建一些基于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使用new关键字来创建它的类,因为从我的实验来看,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 个答案:

答案 0 :(得分:2)

这种方法应该完美无缺。您可能缺少的一件事是,使用这种技术,您不会创建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);
}

答案 1 :(得分:0)

我不完全确定问题是什么,但我会尽力回答我的想法。

new关键字用于实例化由函数原型上的init属性定义的函数返回的对象的新实例。

我相信代码是以这种方式编写的,因此每次实例化一个新的 jQuery 对象时都不需要new关键字,并且还要将对象构造背后的逻辑委托给原型。前者我认为是使库更清洁使用,后者将初始化逻辑保持在一个地方,并允许递归调用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关键字,您都能正确地获得一个返回的对象,其中y属性值为1,new属性值为2。 / p>

答案 2 :(得分:0)

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关键字来创建对象。

另一方面,如果在调用时没有使用new关键字,那么对初始化对象使用init函数的代码将不起作用。要修复它,您必须添加一些代码,例如“J-P”示例来检查此对象。如果它的类型不是当前类,它将自动为它创建实例。

两个代码都可以正常工作。但我喜欢jQuery风格而不是“J-P”风格,因为它很容易阅读和修改。

<强>谢谢,