Home >Web Front-end >JS Tutorial >jQuery constructor init parameter analysis_jquery
In my last essay, I analyzed the constructor of jQuery. There is a prototype method init in the jQuery object, which is the real constructor. The prototype object of init maintains a reference relationship with the prototype object of jQuery so that init's The instance can call jQuery's prototype methods normally, just as if it were an instance of jQuery. Let’s take a look at how the behind-the-scenes constructor init is written:
init: function( selector, context, rootjQuery ) { ... }
You can see that this method accepts 3 parameters, the first two parameters are passed by the jQuery method
var jQuery = function( selector, context ) { // The jQuery object is actually just the init constructor 'enhanced' return new jQuery.fn.init( selector, context, rootjQuery ); },
Selector can in principle enter any value, but not all values are meaningful. Only undefined, DOM elements, strings, functions, jQuery objects, and ordinary JavaScript objects are valid. This parameter is Usually it is filled in but no error will be reported if you don’t fill it in
Context can be passed in as the execution context or execution scope, or it can be passed in one of the DOM elements, jQuery objects, and ordinary JavaScript objects
Parameter rootjQuery: jQuery object containing the document object, used when document.getElementById() fails to find, selector is a selector expression and no context is specified, and selector is a function, it is actually $(document).
The following is divided into 12 situations and discussed one by one according to different parameters
1.selector can be converted to false
// Handle $(""), $(null), or $(undefined) if ( !selector ) { return this; }
The comments in the source code have been written very clearly. In these three situations, return directly without any processing
2. The parameter selector is a DOM element
For example: $(document)
// Handle $(DOMElement) if ( selector.nodeType ) { this.context = this[0] = selector; this.length = 1; return this; }
As long as it is a dom element, it must have a node type, and then turn this node into the first element of the jquery object and assign it to the context. The length attribute is jQuery's prototype attribute and defaults to 0
// The default length of a jQuery object is 0
length: 0,
After there is an element here, change the length attribute to 1. The return this operation makes the result of the function execution still a jQuery object, so that chain calls like $(document).each() can be implemented. The final object obtained is similar to {0:document,context:document,length:1....}. In fact, all situations will eventually become objects in this form, except for jQuery prototype properties and methods. The DOM nodes are arranged in order by Arabic numerals, so we can use the form $(selector)[0] instead of $(selector).get(0) to obtain the DOM object. For example:
<!doctype html> <html> <head> <title></title> </head> <body> <div></div> <div></div> <div></div> </body> <script src='jquery-1.7.1.js'></script> <script> console.log($('div')); /*[div, div, div, prevObject: jQuery.fn.jQuery.init[1], context: document, selector: "div", constructor: function, init: function…] 0: div 1: div 2: div context: document length: 3 prevObject: jQuery.fn.jQuery.init[1]__proto__: jQuery[0] selector: "div" . */ </script> </html>
3. The parameter is the special string "body"
Since there is only one body element in a document object, it is listed separately for processing
// 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; }
There are three conditions here that must be met at the same time. I don’t quite understand the second condition that there must be no context. A seemingly normal writing method such as $('body',document) will also be "ignored" by this situation. ”
console.log($('body',document)); /* jQuery.fn.jQuery.init[1] 0: body context: document length: 1 prevObject: jQuery.fn.jQuery.init[1] selector: "body" __proto__: jQuery[0] */
Although the result is the same as $('body'), it is treated as two situations. It may be because body only has one context and it can only be document. There is no need to add it. Otherwise, you have to judge whether the context is document. The third condition is to ensure that document.body must exist. So under what circumstances will the first two conditions be satisfied but document.body does not exist? The first is that when the js code is loaded before the html code, this is a mistake that beginners often make. Usually we have to write:
$(function(){...})
or
$(document).ready(function(){...})
In fact, these two are the same and call the same method. The DOM will load this part and analyze it later. For this we can make a test html code as follows:
<!doctype html> <html> <head> <title></title> <script src='jquery-1.7.1.js'></script> <script> $('body') </script> </head> <body> <div></div> <div></div> <div></div> </body> </html>
Then output the selector, context and document.body in the jQuery source code
console.log(selector+context+document.body); // 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; }
Although we only wrote one, it was actually executed four times. Only the last time was the result after we called it. The last result was bodyundefinednull. At this time, the first two are satisfied, but the last one is null. Recall that in the first jQuery overall architecture, undefined will be rewritten, so will document.body be rewritten as null? When I try to modify the code, an error will be reported. It seems that it is not possible. Then this condition is to prevent execution without loading the html
The fourth type is strings other than the above-mentioned string situations. We will leave more situations in the next article.
The above is the entire content of this article, I hope you all like it.