jQuery source code analysis of init detailed introduction
- 2021-07-18 07:11:53
- OfStack
init Constructor
Because this function directly and
jQuery()
First, let's talk about what kind of parameters we can accept.
Three parameters are accepted in the source code:
init: function (selector, context, root) {
...
}
jQuery()
Null parameter, this will directly return an empty jQuery object, return this.
jQuery( selector [, context ] )
This is a standard and commonly used method. selector represents an css selector, which is usually a string, # id or.class, etc. context represents the selection range, that is, the limiting effect, which can be DOM and jQuery objects.
jQuery( element|elements )
To encapsulate an DOM object or an DOM array into an jQuery object.
jQuery( jQuery object|object )
Will wrap a normal object or an jQuery object in an jQuery object.
jQuery( html [, ownerDocument ] )
This method is used to convert an html string to an DOM object before generating an jQuery object.
jQuery( html, attributes )
Same as the previous method 1, except that the methods and properties in attributes are bound to the generated html DOM, such as class, and so on.
jQuery( callback )
This method accepts a drop-back function, which is equivalent to the window. onload method, but relative to.
After introducing the entrance, we began to look at the source code.
init: function (selector, context, root) {
var match, elem;
// Deal with : $(""), $(null), $(undefined), $(false)
if (!selector) {
return this;
}
// rootjQuery = jQuery( document );
root = root || rootjQuery;
// Deal with HTML String conditions, including $("<div>") , $("#id") , $(".class")
if (typeof selector === "string") {
// This part is split up and left to be discussed later
// HANDLE: $(DOMElement)
} else if (selector.nodeType) {
this[0] = selector;
this.length = 1;
return this;
// HANDLE: $(function)
} else if (jQuery.isFunction(selector)) {
return root.ready !== undefined ? root.ready(selector) :
// Execute immediately if ready is not present
selector(jQuery);
}
return jQuery.makeArray(selector, this);
}
There are a few points to note,
root = root || rootjQuery;
This parameter, which was not mentioned when we introduced usage earlier, means document, which defaults to rootjQuery, and
rootjQuery = jQuery( document )
.
It can be seen that for processing
jQuery()
0
Which directly treats jQuery as an array,
this[0] = DOMElement
. In fact, this should start with the basic structure of jQuery, and we have completed 1
$('div.span')
Then, there is an jQuery object (this), which results in a set (1) of DOM objects. jQuery adds this set of DOM objects as array elements and gives an length. Later, just like some chain functions, if you can only operate on one DOM, such as width and height, you can only operate on the first element. If you can operate on multiple DOM, you will operate on all DOM, such as css ().
The idea of jQuery is as follows, which is a very simple implementation:
jQuery.prototype = {
// To be simple, let's say that at this time selector Use querySelectorAll
init: function(selector){
var ele = document.querySelectorAll(selector);
// Put this As an array, each 1 Items are DOM Object
for(var i = 0; i < ele.length; i++){
this[i] = ele[i];
}
this.length = ele.length;
return this;
},
//css If only 1 Object, take its first 1 A DOM Object
// If css There are two parameters, the value of each 1 A DOM Object is set css
css : function(attr,val){
for(var i = 0; i < this.length; i++){
if(val == undefined){
if(typeof attr === 'object'){
for(var key in attr){
this.css(key, attr[key]);
}
}else if(typeof attr === 'string'){
return getComputedStyle(this[i])[attr];
}
}else{
this[i].style[attr] = val;
}
}
},
}
Therefore, for the processing of DOMElement, after directly assigning DOM to the array, return this.
jQuery.makeArray
Is a binding array function, and the above principle 1, which will be discussed later.
Before going into the following, let's introduce a regular expression in an jQuery that recognizes an Html string,
var rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;
rquickExpr.exec('<div>') //["<div>", "<div>", undefined]
rquickExpr.exec('<div></div>') //["<div></div>", "<div></div>", undefined]
rquickExpr.exec('#id') //["#id", undefined, "id"]
rquickExpr.exec('.class') //null
The above 1 series of regular expressions exec, just to explain the result of the regular expression rquickExpr after execution, first, if the match, the length of the result array is 3, if the match < div > For this html, the third element of the array is underfined, if # id matches, the second element of the array is underfined, if not, null.
There is also one regular expression:
var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i );
rsingleTag.test('<div></div>') //true
rsingleTag.test('<div ></div>') //true
rsingleTag.test('<div class="cl"></div>') //false
rsingleTag.test('<div></ddiv>') //false
This regular expression is mainly used to verify the string of html, so as to achieve the effect of no errors. I won't introduce exec and regular expressions much here.
Let's take a look at the key processing of HTMl strings:
if (selector[0] === "<" && selector[selector.length - 1] === ">" && selector.length >= 3) {
// This is actually forcibly constructing a match html An array of cases of
match = [null, selector, null];
} else {
match = rquickExpr.exec(selector);
}
// macth[1] Limit html , !context Right #id Deal with
if (match && (match[1] || !context)) {
// HANDLE: $(html) -> $(array)
if (match[1]) {
// Exclude context Yes jQuery Object situation
context = context instanceof jQuery ? context[0] : context;
// jQuery.merge Is specifically for jQuery Method of merging arrays
// jQuery.parseHTML Is aimed at html String is converted to DOM Object
jQuery.merge(this, jQuery.parseHTML(
match[1], context && context.nodeType ? context.ownerDocument || context : document, true));
// HANDLE: $(html, props)
if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) {
for (match in context) {
// At this time match Not at that time match
if (jQuery.isFunction(this[match])) {
this[match](context[match]);
// ...and otherwise set as attributes
} else {
this.attr(match, context[match]);
}
}
}
return this;
// Deal with match(1) For underfined But !context The situation of
} else {
elem = document.getElementById(match[2]);
if (elem) {
// this[0] Return 1 A standard jQuery Object
this[0] = elem;
this.length = 1;
}
return this;
}
// Deal with 1 Like a situation, find Actually Sizzle , jQuery It has been included and described in detail in the next chapter
// jQuery.find() For jQuery Selector with good performance
} else if (!context || context.jquery) {
return (context || root).find(selector);
// Deal with !context Situation
} else {
// Here constructor Actually it is Point jQuery Adj.
return this.constructor(context).find(selector);
}
For nodeType, this is an attribute of DOM, details Node. nodeType MDN. The value 1 of nodeType is generally a number, for example, 1 represents DOM, 3 represents text, etc. DOM elements can also be judged by whether this value exists, such as context. nodeType.
The whole init function and other construction logic are very clear, such as (selector, context, root) three parameters, which respectively represent the selected content, possible restricted objects or Object, while root is the default
jQuery(document)
. It still adopts the common way of jQuery, and is very cautious in handling every 1 variable.
If you look at the above two parts of the source code carefully, I also added comments, should be able to understand the whole process.
The find function is actually Sizzle, and a separate project has been developed and used directly in jQuery. The Sizzle selector in jQuery will be introduced in the next chapter. Through the source code, you can find:
jQuery.find = function Sizzle(){...}
jQuery.fn.find = function(selector){
...
// Quote jQuery.find
jQuery.find()
...
}
Derived function
The init function still calls a number of jQuery or
jQuery.fn
The functions of, let's analyze them one by one.
jQuery.merge
This function knows what it is used for by its name, merging.
jQuery.merge = function (first, second) {
var len = +second.length,
j = 0,
i = first.length;
for (; j < len; j++) {
first[i++] = second[j];
}
first.length = i;
return first;
}
In this way, you can merge types that are similar to arrays and have length parameters. I feel that it is mainly for the convenience of merging jQuery objects, because jQuery objects have length.
jQuery.parseHTML
This function is also very interesting, which is to convert a string of HTML strings into DOM objects.
Firstly, the function accepts three parameters, the first parameter data is html string, and the second parameter is document object. However, considering the compatibility of browsers, the third parameter keepScripts is to delete all script tags in nodes, but it is not reflected in parseHTML, mainly giving buildFragment as a parameter.
In short, the returned object is an DOM array or an empty array.
jQuery.parseHTML = function (data, context, keepScripts) {
if (typeof data !== "string") {
return [];
}
// Translation parameter
if (typeof context === "boolean") {
keepScripts = context;
context = false;
}
var base, parsed, scripts;
if (!context) {
// The meaning of the following passage is to context In case of absence, establish 1 A document Object
if (support.createHTMLDocument) {
context = document.implementation.createHTMLDocument("");
base = context.createElement("base");
base.href = document.location.href;
context.head.appendChild(base);
} else {
context = document;
}
}
// Used to parse parsed For example, right "<div></div>" Processing results of parsed : ["<div></div>", "div"]
// parsed[1] = "div"
parsed = rsingleTag.exec(data);
scripts = !keepScripts && [];
// Single tag
if (parsed) {
return [context.createElement(parsed[1])];
}
// See explanation below
parsed = buildFragment([data], context, scripts);
if (scripts && scripts.length) {
jQuery(scripts).remove();
}
return jQuery.merge([], parsed.childNodes);
}
buildFragment function is mainly used to establish an fragment object containing child nodes, which is used to add and delete nodes in frequent operations.
parsed = buildFragment([data], context, scripts);
Establish an fragment object and use it
parsed.childNodes
To obtain the HTML corresponding to these data.
jQueyr.makeArray
The function call in jQuery is really one layer after another. Although sometimes the function name alone can know the function's function, the logic of thinking is quite referential.
jQuery.makeArray = function (arr, results) {
var ret = results || [];
if (arr != null) {
if (isArrayLike(Object(arr))) {
jQuery.merge(ret, typeof arr === "string" ? [arr] : arr);
} else {
push.call(ret, arr);
}
}
return ret;
}
makeArray merges the left-hand array or string into the right-hand array or a new array in which an indirect reference
jQuery.merge
Function.
Next is the isArrayLike function, which may need to consider many factors, such as compatible browsers, etc., and there is the following 1 long string:
init: function (selector, context, root) {
var match, elem;
// Deal with : $(""), $(null), $(undefined), $(false)
if (!selector) {
return this;
}
// rootjQuery = jQuery( document );
root = root || rootjQuery;
// Deal with HTML String conditions, including $("<div>") , $("#id") , $(".class")
if (typeof selector === "string") {
// This part is split up and left to be discussed later
// HANDLE: $(DOMElement)
} else if (selector.nodeType) {
this[0] = selector;
this.length = 1;
return this;
// HANDLE: $(function)
} else if (jQuery.isFunction(selector)) {
return root.ready !== undefined ? root.ready(selector) :
// Execute immediately if ready is not present
selector(jQuery);
}
return jQuery.makeArray(selector, this);
}
0
Summarize
This article mainly introduces the important entry functions in jQuery, and will continue to explain the selectors in Sizzle and jQuery. Interested friends, please continue to pay attention to this site, thank you for your support.