Wednesday, July 20, 2011

learning jQuery source code (v1.6.2) - 2

Continue from the last post http://hengrui-li.blogspot.com/2011/07/learning-jquery-source-code-v162.html, we know that jQuery object is actually generated by the code below:
var jQuery = function( selector, context ) {
     // The jQuery object is actually just the init constructor 'enhanced'
     return new jQuery.fn.init( selector, context, rootjQuery );
}
Today we will learn how jQuery.fn.init function works. When i look at a function, I always look at the function signature first, and then, try to look at what it returns. At this stage, i don't have to worry about its implementation details.

jQuery.fn = jQuery.prototype = {
            constructor: jQuery,
            init: function( selector, context, rootjQuery ) {
                        ...
                        return jQuery.makeArray( selector, this );
            },
...
} 
Well, jQuery is an excellent js lib, but i still have to say i don't like functions without any annotation at the top.

We see the function takes three parameters. 'selector' probably is the easiest one to understand: when we call $("#id"), "#id" is the selector. Let's leave the other two parameters for now.

We look at what this function will return at the last line: "return jQuery.makeArray( selector, this );". Usually, i look at the last return statement to grab the first impression that what a function could return. However, it is also quite common that a function has multiple return statements. I think it is a good practice that we should try to avoid multiple return statements within one function, but, sometimes, it does make our life easier, so i can accept that. One thing i really insist is the function's return type must be consistent. That means, if a function is supposed to return a boolean value, it should only return true or false. It is bad that it returns true at one place, at another place it returns null, and at another place it returns empty string '' etc. In general, a function should return only one type of data. It is a bad practice that a function could return multiple types. "return jQuery.makeArray( selector, this );" tells us the function could return an array(object). I don't know what jQuery.makeArray really does but it doesn't matter as long as its name is not misleading.

Now let's look at the implementation details step by step.
code 1:
// Handle $(""), $(null), or $(undefined)
if ( !selector ) {
     return this;
}
The comment is quite clear here. if we do $("") kindof stuff, it simply returns this.

code 2:
// Handle $(DOMElement)
if ( selector.nodeType ) {
            this.context = this[0] = selector;
            this.length = 1;
            return this;
}

Again, the comment tells all. To see what it does, we can write some logs in the code, and try:
var dom = document.getElementById('id');
$(dom);

From this code, we can find that jQuery makes this[0] refers to the dom elements we are querying.

code 3:
// The body element only exists once, optimize finding it
if ( selector === "body" && !context && document.body ) {
    this.context = document;
    this[0] = document.body;
    this.selector = selector;
    this.length = 1;
    return this;
}
This simply optimizes the way to find body element.

code 4:
// Handle HTML strings
if ( typeof selector === "string" ) {
...
}
This is the most complex block cause it is handling the most common tasks like $("#id"), $('input[name="name"]'), etc. We will look at it next time.

No comments: