开发者

Why does jQuery use "new jQuery.fn.init()" for creating jQuery object but I can't?

开发者 https://www.devze.com 2022-12-13 14:14 出处:网络
I try to create some class based-on jQuery style like the following code. myClass = window.myClass = function(x, y)

I try to create some class based-on jQuery style like the following code.

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.
    }
};

I do not understand why jQuery use new keyword for creating its class because from my experiment, JavaScript always create myClass.init object instead of myClass object. However, I try to remove new keyword in myClass constructor. But it still not changes. Can you explain why jQuery can do that but I can’t or give me some code for using in init function?

By the way, I can use the following c开发者_JAVA百科ode instead of jQuery style code for creating the same object. What is the different between my code & jQuery code? Are there any benefit for using jQuery style?

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. I like write code that separate initial logic into function because it is very easy to override this function by other people that use my code like my following code.

// 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
};

Thanks,


This approach should work perfectly. One thing you may be missing is the fact that, using this technique, you're not going to be creating an instance of myClass; you're going to be creating an instance of myClass.prototype.init.

So, any methods defined in myClass.prototype won't be available to the instance. You'll want to make sure that the init's prototype points to myClass's prototype:

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

FWIW, I don't see any real benefit in this approach. What's wrong with this? -

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);
}


The jQuery object initialization should like the following code.

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;

The only one benefit of this code is it always create instance of jQuery object although you do not use new keyword for creating object.

In the other hand, my code that use init function for initialization object does not work if you do not use new keyword when call it. For fixing it, you must add some code like "J-P" example for checking this object. If type of it is not current class, it will automatically create instance for it.

Both of codes should work fine. But I like jQuery style more than "J-P" style because it is quite easy to read and modify.

Thanks,


I'm not entirely sure what the question is, but I'll do my best to answer what I think you're asking.

the new keyword is used to instantiate a new instance of the object returned by the function defined by the init property on the function prototype.

I believe the code is written in this fashion so that the new keyword is not required each time you instantiate a new jQuery object and also to delegate the logic behind the object construction to the prototype. The former I believe is to make the library cleaner to use and the latter to keep the initialisation logic cleanly in one place and allow init to be recursively called to construct and return an object that correctly matches the passed arguments.

Your second block of code does not return an object. Try it out in Firebug with

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

you get this.init is not a function error. The only way that this would work is if you use the new keyword as in

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

Compare that with the code similar to that in 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);

In each case, you correctly get an object returned with an x property with value 1 and a y property with value 2, whether the new keyword is used or not.

0

精彩评论

暂无评论...
验证码 换一张
取 消