Implementation Code of the jquery constructor _ jquery

Source: Internet
Author: User
The $ symbol of jQuery is amazing. It can accept a single character, a document object, or a window object, or pass a function to the domReady loader. Obviously, this step can be done, its implementation is quite complicated. This implementation is its init method, the real constructor of jQuery. Its functions also become longer and longer as the version is upgraded.
Version 1.3 released on

The Code is as follows:


Init: function (selector, context ){
// Make sure that a selection was provided
Selector = selector | document;
// Process node parameters and add attributes directly to the new instance
If (selector. nodeType ){
This [0] = selector;
This. length = 1;
This. context = selector;
Return this;
}
// Process string Parameters
If (typeof selector = "string "){
// Determine whether it is an HTML part or an ID
Var match = quickExpr.exe c (selector );
If (match & (match [1] |! Context )){
// If it is an HTML segment, convert an array constructed by nodes
If (match [1])
Selector = jQuery. clean ([match [1], context );
// If it is an ID, search for this element. If it is found and put into an empty array
Else {
Var elem = document. getElementById (match [3]);
// Make sure an element was located
If (elem ){
// Handle the bug of confusing ID and NAME in IE and Opera
If (elem. id! = Match [3])
Return jQuery (). find (selector );
Var ret = jQuery (elem );
Ret. context = document;
Ret. selector = selector;
Return ret;
}
Selector = [];
}
} Else
// Use Sizzle to process other CSS expressions, generate instances, and return
Return jQuery (context). find (selector );
// Process the function parameters, directly domReady
} Else if (jQuery. isFunction (selector ))
Return jQuery (document). ready (selector );
// Process the parameters of the jQuery object and assign the two attributes to the new instance.
If (selector. selector & selector. context ){
This. selector = selector. selector;
This. context = selector. context;
}
// Convert the preceding node arrays into instance elements using the setArray method.
Return this. setArray (jQuery. makeArray (selector ));
},


Version 1.32 released on February 19

The Code is as follows:


Init: function (selector, context ){
// Make sure that a selection was provided
Selector = selector | document;
// Process node parameters and add attributes directly to the new instance
If (selector. nodeType ){
This [0] = selector;
This. length = 1;
This. context = selector;
Return this;
}
// Process string Parameters
If (typeof selector = "string "){
// Determine whether it is an HTML part or an ID
Var match = quickExpr.exe c (selector );
If (match & (match [1] |! Context )){
// If it is an HTML segment, convert an array constructed by nodes
If (match [1])
Selector = jQuery. clean ([match [1], context );
Else {
Var elem = document. getElementById (match [3]);
// If it is an ID, search for this element. If it is found and put into an empty array
If (elem & elem. id! = Match [3])
Return jQuery (). find (selector );
// Some optimizations have been made for version 1.3, which is more concise.
Var ret = jQuery (elem | []);
Ret. context = document;
Ret. selector = selector;
Return ret;
}
} Else
// Use Sizzle to process other CSS expressions, generate instances, and return
Return jQuery (context). find (selector );
// Process the function parameters and perform the domReady operation
} Else if (jQuery. isFunction (selector ))
Return jQuery (document). ready (selector );
// Process the parameters of the jQuery object and assign the two attributes to the new instance.
If (selector. selector & selector. context ){
This. selector = selector. selector;
This. context = selector. context;
}
// Some extensions have been made for version 1.3, allowing the Element Set (HTMLCollection) and node set (NodeList) on the treasures to be uploaded ),
// Element arrays may be converted using strings or directly transmitted by users.
Return this. setArray (jQuery. isArray (selector )? Selector: jQuery. makeArray (selector ));
},


Version 1.4 released on

The Code is as follows:


Init: function (selector, context ){
Var match, elem, ret, doc;
// Process the blank string, null, undefined parameter (new), and return a very pure instance
If (! Selector ){
Return this;
}
// Process node parameters and add attributes directly to the new instance
If (selector. nodeType ){
This. context = this [0] = selector; // write Optimization
This. length = 1;
Return this;
}
// Process string Parameters
If (typeof selector = "string "){
// Determine whether it is an HTML part or an ID
Match = quickExpr.exe c (selector );
If (match & (match [1] |! Context )){
// For HTML clips
If (match [1]) {
// Obtain the Document Object
Doc = (context? Context. ownerDocument | context: document );
// For a single label, use document. createElement to create the node and put it in the array.
Ret = rsingleTag.exe c (selector );
If (ret ){
// If a pure JS object is followed, add the corresponding attribute or style to the node.
If (jQuery. isPlainObject (context )){
Selector = [document. createElement (ret [1])];
JQuery. fn. attr. call (selector, context, true );
} Else {
Selector = [doc. createElement (ret [1])];
}
} Else {
// Changed buildFragment to generate a node set (NodeList)
Ret = buildFragment ([match [1], [doc]);
Selector = (ret. cacheable? Ret. fragment. cloneNode (true): ret. fragment). childNodes;
}
} Else {
// If it is an ID, search for this element. If it is found and put into an empty array
Elem = document. getElementById (match [2]);
If (elem ){
// Handle the bug of confusing ID and NAME in IE and Opera
If (elem. id! = Match [2]) {
Return rootjQuery. find (selector );
}
// Some optimizations have been made here. It turns out to be silly to regenerate a jQuery instance.
This. length = 1;
This [0] = elem;
}
This. context = document;
This. selector = selector;
Return this;
}
// If the character is a very simple tag selector, there is basically no need to take the Sizzle route, directly getElementsByTagName, very good Optimization
} Else if (! Context &/^ \ w + $/. test (selector )){
This. selector = selector;
This. context = document;
Selector = document. getElementsByTagName (selector );
// If the second parameter does not exist or is a jQuery object, use it or rootjQuery to call find to find the target node (taking the Sizzle path)
} Else if (! Context | context. jquery ){
Return (context | rootjQuery). find (selector );
// HANDLE: $ (expr, context)
// (Which is just equivalent to: $ (context). find (expr)
} Else {
// If the second parameter has been specified as an element node, convert it to a jQuery object and follow the Sizzle route
Return jQuery (context). find (selector );
}
// Process the function parameters, directly domReady
} Else if (jQuery. isFunction (selector )){
Return rootjQuery. ready (selector );
}
// Process the parameters of the jQuery object and assign the two attributes to the new instance.
If (selector. selector! = Undefined ){
This. selector = selector. selector;
This. context = selector. context;
}
// Some modifications are made here, because makeArray can accept the second parameter (which can be an array or an array of classes, which is equivalent to the merge operation)
Return jQuery. isArray (selector )?
This. setArray (selector): // use the push method internally to quickly change a common object to an array object of the class.
JQuery. makeArray (selector, this );
},


Next is the popular version 1.42 released by 2010-02-13.

The Code is as follows:


Init: function (selector, context ){
Var match, elem, ret, doc;
// Process the blank string, null, undefined Parameter
If (! Selector ){
Return this;
}
// Process node parameters
If (selector. nodeType ){
This. context = this [0] = selector;
This. length = 1;
Return this;
}
// Process the body parameter (new)
If (selector = "body "&&! Context ){
This. context = document;
This [0] = document. body;
This. selector = "body ";
This. length = 1;
Return this;
}
// Process string parameters in seven cases:
// ① Single tag with Object Property package ---> jQuery. merge
// ② Single tag without the object property package ---> attr + jQuery. merge
// ③ Complex HTML snippets ---> buildFragment + jQuery. merge
// ④ ID selector, which is different from the ID of the element found ---> getElementById + Sizzle + pushStack
// ⑤ ID selector, which is the same as the ID of the element found ---> getElementById + simple attribute add
// ⑥ Tag selector ---> getElementsByTagName + jQuery. merge
// Other CSS expressions ---> Sizzle + pushStack
If (typeof selector = "string "){
Match = quickExpr.exe c (selector );
If (match & (match [1] |! Context )){
If (match [1]) {
Doc = (context? Context. ownerDocument | context: document );
Ret = rsingleTag.exe c (selector );
If (ret ){
If (jQuery. isPlainObject (context )){
Selector = [document. createElement (ret [1])];
JQuery. fn. attr. call (selector, context, true );
} Else {
Selector = [doc. createElement (ret [1])];
}
} Else {
Ret = buildFragment ([match [1], [doc]);
Selector = (ret. cacheable? Ret. fragment. cloneNode (true): ret. fragment). childNodes;
}
Return jQuery. merge (this, selector );
} Else {
Elem = document. getElementById (match [2]);
If (elem ){
If (elem. id! = Match [2]) {
Return rootjQuery. find (selector );
}
This. length = 1;
This [0] = elem;
}
This. context = document;
This. selector = selector;
Return this;
}
} Else if (! Context &/^ \ w + $/. test (selector )){
This. selector = selector;
This. context = document;
Selector = document. getElementsByTagName (selector );
Return jQuery. merge (this, selector );
} Else if (! Context | context. jquery ){
Return (context | rootjQuery). find (selector );
} Else {
Return jQuery (context). find (selector );
}
// Process the function parameters, directly domReady
} Else if (jQuery. isFunction (selector )){
Return rootjQuery. ready (selector );
}
// Process jQuery object parameters
If (selector. selector! = Undefined ){
This. selector = selector. selector;
This. context = selector. context;
}
// Use jQuery. makeArray to add new elements to the instance, whether it is an array or a class array (such as NodeList ).
Return jQuery. makeArray (selector, this );
},


The makeArray method and merge method are attached. The merge method is amazing,

The Code is as follows:


MakeArray: function (array, results ){
Var ret = results | [];
If (array! = Null ){
// The window, strings (and functions) also have 'length'
// The extra typeof function check is to prevent crashes
// In Safari 2 (See: #3039)
If (array. length = null | typeof array = "string" | jQuery. isFunction (array) | (typeof array! = "Function" & array. setInterval )){
Push. call (ret, array );
} Else {
JQuery. merge (ret, array );
}
}
Return ret;
},
Merge: function (first, second ){
Var I = first. length, j = 0;
If (typeof second. length = "number "){
For (var l = second. length; j <l; j ++ ){
First [I ++] = second [j];
}
} Else {
While (second [j]! = Undefined ){
First [I ++] = second [j ++];
}
}
First. length = I;
Return first;
},


In version 1.5 released from, the init method and 1.42 have not changed much: only two changes have been made:

The Code is as follows:


// 1.42
-Ret = buildFragment ([match [1], [doc]);
-Selector = (ret. cacheable? Ret. fragment. cloneNode (true): ret. fragment). childNodes;
// 1.5
+ Ret = jQuery. buildFragment ([match [1], [doc]);
+ Selector = (ret. cacheable? JQuery. clone (ret. fragment): ret. fragment). childNodes;
// 1.42
-Return jQuery (context). find (selector );
// 1.5
+ Return this. constructor (context). find (selector); // The objective is not to regenerate a new instance.


Jquery1.6 released in has not changed much, but it makes a more rigorous judgment on HTML fragments:

The Code is as follows:


// Are we dealing with HTML string or an ID?
If (selector. charAt (0) = "<" & selector. charAt (selector. length-1) ==="> "& selector. length> = 3 ){
// Assume that strings that start and end with <> are HTML and skip the regex check
Match = [null, selector, null];
} Else {
Match = quickExpr.exe c (selector );
}


In general, the jQuery constructor has done a perfect job, basically reaching the point of "unchangeable. However, to ensure its efficient operation, we also need a little knowledge of selector and understanding how the buildFragment method works, because these two are too common, but also the most performance-consuming.
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.