Home >Web Front-end >JS Tutorial >Summary of the implementation code of jquery constructor_jquery

Summary of the implementation code of jquery constructor_jquery

WBOY
WBOYOriginal
2016-05-16 18:06:41867browse

Obviously, the implementation to achieve this step is quite complicated. This implementation is its init method, the real constructor of jQuery. Its functions are also upgraded with the version upgrade, and it is getting longer and longer.
Version 1.3 released on 2009-01-13

Copy the code 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;
}
// Processing string parameters
if ( typeof selector === "string" ) {
// Determine whether it is an HTML fragment or an ID
var match = quickExpr.exec( selector );
if ( match && (match[1] || !context) ) {
// If it is an HTML fragment, convert an array constructed from nodes
if ( match[1] )
selector = jQuery.clean( [ match[1] ], context );
// If it is an ID, search for this element, and if found, put it into an empty array
else {
var elem = document.getElementById( match[3] ) ;
// Make sure an element was located
if ( elem ){
// Deal with the bug of confusion between 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 function parameters, directly domReady
} else if ( jQuery.isFunction( selector ) )
return jQuery( document ).ready( selector );
// Process jQuery object parameters, simple Assign its two properties to the new instance
if ( selector.selector && selector.context ) {
this.selector = selector.selector;
this.context = selector.context;
}
//Convert the node arrays obtained above and use the setArray method to turn them into instance elements
return this.setArray(jQuery.makeArray(selector));
},

Version 1.32 released on 2009-02-19
Copy code 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;
}
//Processing characters String parameter
if ( typeof selector === "string" ) {
//Determine whether it is an HTML fragment or an ID
var match = quickExpr.exec( selector );
if ( match && ( match[1] || !context) ) {
// If it is an HTML fragment, convert an array constructed from 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, and if found, put it into an empty array
if ( elem && elem.id != match[3] )
return jQuery().find( selector );
//Some optimizations have been made here for version 1.3, making it more concise
var ret = jQuery( elem || [] );
ret.context = document;
ret.selector = selector;
return ret;
}
} else
//Use Sizzle Process other CSS expressions, generate instances and return
return jQuery( context ).find( selector );
// Process function parameters and perform domReady operations
} else if ( jQuery.isFunction( selector ) )
return jQuery( document ).ready( selector );
//Process the jQuery object parameters and simply assign its two properties to the new instance
if ( selector.selector && selector.context ) {
this.selector = selector.selector;
this.context = selector.context;
}
//Here are some extensions to version 1.3, allowing the transfer of element collections (HTMLCollection) and nodes Collection (NodeList),
//The element array may be converted by us using a string, or it may be passed in directly by the user
return this.setArray(jQuery.isArray( selector ) ? selector : jQuery.makeArray (selector));
},

Version 1.4 released on 2010-01-13
Copy codeThe code is as follows:

init: function( selector, context ) {
var match, elem, ret, doc;
//Handle blank string, null, undefined parameters (newly added), return a very pure Instance of
if ( !selector ) {
return this;
}
// Process node parameters and directly add attributes to the new instance
if ( selector.nodeType ) {
this.context = this[0] = selector;//Optimized writing
this.length = 1;
return this;
}
//Processing string parameters
if ( typeof selector === "string" ) {
// Determine whether it is an HTML fragment or an ID
match = quickExpr.exec( selector );
if ( match && (match[1] || !context) ) {
//If it is an HTML fragment
if ( match[1] ) {
//Get the document object
doc = (context ? context.ownerDocument || context : document);
// If it is a single tag, directly use document.createElement to create this node and put it into the array
ret = rsingleTag.exec( selector );
if ( ret ) {
//If followed by Pure JS object, add corresponding attributes or styles to this node
if ( jQuery.isPlainObject( context ) ) {
selector = [ document.createElement( ret[1] ) ];
jQuery. fn.attr.call( selector, context, true );
} else {
selector = [ doc.createElement( ret[1] ) ];
}
} else {
/ /Change buildFragment to generate node collection (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, and if found, put it into an empty array
elem = document.getElementById( match[2] );
if ( elem ) {
// Deal with the bug of confusion between ID and NAME in IE and Opera
if ( elem.id !== match[2] ) {
return rootjQuery.find( selector );
}
//Some optimizations have also been done here. It turns out that it is stupid to generate another jQuery instance
this.length = 1;
this[0] = elem;
}
this.context = document;
this.selector = selector;
return this;
}
// If the character is a very simple label selector, there is basically no need to go Sizzle route, getElementsByTagName directly, 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, then use it or rootjQuery to call find to find the target node (take the Sizzle route)
} 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, take the Sizzle route
return jQuery( context ). find( selector );
}
// Process function parameters directly domReady
} else if ( jQuery.isFunction( selector ) ) {
return rootjQuery.ready( selector );
}
//Handle the jQuery object parameters and simply assign its two properties to the new instance
if (selector.selector !== undefined) {
this.selector = selector.selector;
this .context = selector.context;
}
//Some modifications have been made here, because makeArray can accept the second parameter (can be an array or array-like, which is equivalent to a merge operation)
return jQuery.isArray( selector ) ?
this.setArray( selector ) ://Use push method internally to quickly turn an ordinary object into an array-like object
jQuery.makeArray( selector, this );
} , <🎜> >The code is as follows:

init: function( selector, context ) {
var match, elem, ret, doc;
// Handle blank string, null, undefined parameters
if ( !selector ) {
return this;
}
// Process node parameters
if ( selector.nodeType ) {
this.context = this[0] = selector;
this.length = 1 ;
return this;
}
// Process body parameters (new)
if ( selector === "body" && !context ) {
this.context = document;
this[0] = document.body;
this.selector = "body";
this.length = 1;
return this;
}
// Processing string parameters , divided into seven situations:
//①Single label, with object attribute package---> jQuery.merge
//②Single label, without object attribute package---> attr jQuery.merge
//③Complex HTML fragment---> buildFragment jQuery.merge
//④ID selector, which is different from the ID of the found element---> getElementById Sizzle pushStack
//⑤ID selection Device, the same as the ID of the found element ---> getElementById simple attribute addition
//⑥ tag selector ---> getElementsByTagName jQuery.merge
///⑦ other CSS expressions ---> ; Sizzle pushStack
if ( typeof selector === "string" ) {
match = quickExpr.exec( selector );
if ( match && (match[1] || !context) ) {
if ( match[1] ) {
doc = (context ? context.ownerDocument || context : document);
ret = rsingleTag.exec( 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 function parameters directly domReady
} else if ( jQuery.isFunction( selector ) ) {
return rootjQuery.ready( selector );
}
//Processing jQuery object parameters
if (selector.selector !== undefined) {
this.selector = selector.selector;
this.context = selector.context;
}
//Whether it is an array or an array-like (such as NodeList), use jQuery.makeArray to add new elements to the instance
return jQuery.makeArray( selector, this );
},

Attached are the makeArray method and merge method. The merge method is so amazing.
Copy Code 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;
},

2011-01 Version 1.5 released on -23 has little change in the init method from 1.42: only two changes have been made:
Copy code 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 purpose is not to generate new instances

Jquery 1.6 released on 2011-05-02 has not changed much, except for a stricter judgment on HTML fragments:
Copy code 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.exec( selector );
}

In general, the structure of jQuery The instrument has been made very perfect, and it has basically reached the point where "nothing can be changed". But to ensure its efficient operation, we also need some knowledge of selectors and understanding of the operation of the buildFragment method, because these two are too commonly used, but they are also the most performance-consuming.
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn