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.


Related articles: