jQuery(); . JQuery(); function JQuery(); consists of two functions - the main and the so-called cover. You start the cover, the cover starts the main function and returns the result from it. var jQuery = function (selector, context) { return new jQuery.prototype.init(selector, context); }; jQuery(); function jQuery(); it runs the init function with the same parameters from its prototype. The init function is the main one.constructor parameter is not specified. jQuery.prototype = { constructor: jQuery }; jQuery.prototype object and jQuery.fn , thereby setting two parameters for one object in order to be able to add new functions for objects more briefly. jQuery.fn = jQuery.prototype = { constructor: jQuery }; var init = jQuery.prototype.init = function (selector, context) { /** , */ var array = []; /** , * * HTML */ if (typeof selector === 'string') { /** , DOM */ } else if (selector.nodeType) { /** * * */ } else if ({}.toString.call(selector) === '[object Array]') { /** * , * */ } else if ({}.toString.call(selector) === '[object Object]') { /** , ? */ } else if ({}.toString.call(selector) === '[object HTMLCollection]' || {}.toString.call(selector) === '[object NodeList]') { /** β */ } else if ({}.toString.call(selector) === '[object Function]') { /** , */ } else { return array; } }; /** , HTML */ if (selector[0] === "<" && selector[selector.length - 1] === ">" && selector.length >= 3) { /** HTML, */ } else { }; innerHTML insert our string with the code and take the already prepared DOM elements. var parseHTML = function (HTML) { /** * , * * β . * * */ if (typeof HTML === 'string' && HTML[0] === "<" && HTML[HTML.length - 1] === ">" && HTML.length >= 3) { /** */ var E = document.createElement('div'); /** HTML */ E.innerHTML = HTML; /** */ return E.childNodes; } else { /** β , */ return []; }; }; DOMParser(); using the DOMParser(); function DOMParser(); and its additional function parseFromString(); . var parseHTML = function (HTML) { /** * , * * β . * * */ if (typeof HTML === 'string' && HTML[0] === "<" && HTML[HTML.length - 1] === ">" && HTML.length >= 3) { /** HTML */ var DOM = new DOMParser().parseFromString(HTML, 'text/html'); /** */ var DOMList = DOM.body.childNodes; /** */ return DOMList; } else { /** β , */ return []; }; }; document.implementation.createHTMLDocument(); function document.implementation.createHTMLDocument(); . var parseHTML = function (HTML) { /** * , * * β . * * */ if (typeof HTML === 'string' && HTML[0] === "<" && HTML[HTML.length - 1] === ">" && HTML.length >= 3) { /** HTML */ var DOM = document.implementation.createHTMLDocument(); /** HTML */ DOM.body.innerHTML = HTML; /** */ var DOMList = DOM.body.childNodes; /** */ return DOMList; } else { /** β , */ return []; }; }; var parseHTML = function (data, context, keepScripts) { /** , */ if (typeof data !== 'string') { return []; } /** * context * keepScripts, * true/false */ if (typeof context === 'boolean') { keepScripts = context; context = false; }; var DOM, DOMList; if (!context || context === document) { /** HTML */ DOM = document.implementation.createHTMLDocument() || new DOMParser().parseFromString('', 'text/html'); /** HTML */ DOM.body.innerHTML = data; /** */ DOMList = DOM.body.childNodes; } else if (context.nodeType) { /** , */ DOM = document.createElement('div'); /** */ context.appendChild(DOM); /** */ DOM.innerHTML = data; /** */ DOMList = DOM.childNodes; /** DOM */ DOM.parentNode.removeChild(DOM); }; /** , */ if (keepScripts === true) { /** */ var scripts = DOM.scripts || DOM.querySelectorAll('script'); /** */ if (scripts.length) { /** */ for (var i = 0; i < scripts.length; i++) { /** */ var script = document.createElement('script'); /** */ script.innerHTML = scripts[i].innerHTML; if (scripts[i].attributes) script.attributes = scripts[i].attributes; /** HEAD */ document.head.appendChild(script); /** HEAD */ script.parentNode.removeChild(script); }; }; }; /** */ return (function () { var array = []; for (var i = 0; i < DOMList.length; i++) { array[array.length] = DOMList[i]; }; return array; })(); }; var merge = function( first, second ) { var len = +second.length, /** second.length , , ( - , ) */ j = 0, i = first.length; /** */ for ( ; j < len; j++ ) { /** * * * */ first[ i++ ] = second[ j ]; } /** */ first.length = i; /** */ return first; }; jQuery.merge() function:Array.concat(); function Array.concat(); which combines arrays. [0, 1, 2].concat([3, 4, 5]); // [0, 1, 2, 3, 4, 5] [].slice.call() function. [0, 1, 2].concat( [].slice.call(document.querySelectorAll(selector)) ); // [0, 1, 2, element, element] var elements = document.querySelectorAll(selector); var array = []; for (var i = 0; i < elements.length; i++) { array[array.length] = elements[i]; }; [0, 1, 2].concat(array); // [0, 1, 2, element, element] var merge = function (array0, array1) { for (var i = 0; i < array1.length; i++) { array0[array0.length] = array1[i]; /** * array0.push(array1[i]); * */ }; return array0; }; merge([0, 1, 2], [3, 4, 5]); // [0, 1, 3, 4, 5, 6] context argument is an object with parameters. If yes, then write all the parameters with arguments to the DOM elements. if ({}.toString.call(context) === '[object Object]') { for (var i = 0; i < array.length; i++) { for (var argument in context) { array.setAttribute(argument, context[argument]); }; }; }; Sizzle( String selector ); document.querySelectorAll( String selector ); . The only drawback of this method in front of the Sizzle library is that it only works with IE9 +.context argument and make sure that it is not an element or elements in which to search for elements by a selector. I will not paint every step, as I explained all the steps in the code. /** * , context * , * selector */ /** context */ if (context && context.nodeType) { /** */ var Elements = context.querySelectorAll(selector); /** */ return jQuery.merge(array, Elements); /** context */ } else if ({}.toString.call(context) === '[object HTMLCollection]' || {}.toString.call(context) === '[object NodeList]') { /** * * */ for (var i = 0; i < context.length; i++) { /** */ var Elements = context[i].querySelectorAll(selector); /** */ jQuery.merge(array, Elements); }; /** */ return array; /** context */ } else if (typeof context === 'string') { /** * */ var Parents = document.querySelectorAll(context); /** * * */ for (var i = 0; i < Parents.length; i++) { /** */ var Elements = Parents[i].querySelectorAll(selector); /** */ jQuery.merge(array, Elements); }; /** */ return array; /** * , * */ } else { /** */ var Elements = document.querySelectorAll(selector); /** */ return jQuery.merge(array, Elements); }; .find(); . Therefore, the jQuery(selector, elements); entry jQuery(selector, elements); is an abbreviated function jQuery(elements).find(selector); var init = jQuery.prototype.init = function (selector, context) { /** , */ var array = []; /** , * * HTML */ if (typeof selector === 'string') { /** , HTML */ if (selector[0] === "<" && selector[selector.length - 1] === ">" && selector.length >= 3) { /** HTML */ jQuery.merge(array, jQuery.parseHTML(selector, context && context.nodeType ? context.ownerDocument || context : document, true)); /** , context * . , * DOM . */ if ({}.toString.call(context) === '[object Object]') { for (var i = 0; i < array.length; i++) { for (var argument in context) { array.setAttribute(argument, context[argument]); }; }; }; /** */ return array; /** HTML, */ } else { /** * , context * , * selector */ /** context */ if (context && context.nodeType) { /** */ var Elements = context.querySelectorAll(selector); /** */ return jQuery.merge(array, Elements); /** context */ } else if ({}.toString.call(context) === '[object HTMLCollection]' || {}.toString.call(context) === '[object NodeList]') { /** * * */ for (var i = 0; i < context.length; i++) { /** */ var Elements = context[i].querySelectorAll(selector); /** */ jQuery.merge(array, Elements); }; /** */ return array; /** context */ } else if (typeof context === 'string') { /** * */ var Parents = document.querySelectorAll(context); /** * * */ for (var i = 0; i < Parents.length; i++) { /** */ var Elements = Parents[i].querySelectorAll(selector); /** */ jQuery.merge(array, Elements); }; /** */ return array; /** * , * */ } else { /** */ var Elements = document.querySelectorAll(selector); /** */ return jQuery.merge(array, Elements); } }; /** , DOM */ } else if (selector.nodeType) { /** * * */ } else if ({}.toString.call(selector) === '[object Array]') { /** * , * */ } else if ({}.toString.call(selector) === '[object Object]') { /** , ? */ } else if ({}.toString.call(selector) === '[object HTMLCollection]' || {}.toString.call(selector) === '[object NodeList]') { /** β */ } else if ({}.toString.call(selector) === '[object Function]') { /** , */ } else { return array; } }; /** */ array[0] = selector; /** */ return array; /** */ jQuery.merge(array, selector); /** */ return array; /** */ array[0] = selector; /** */ return array; /** */ jQuery.merge(array, selector); /** */ return array; jQuery( Function ); is an abbreviated function jQuery(document).ready( Function ); . var ready = (function() { var readyList, DOMContentLoaded, class2type = {}; class2type["[object Boolean]"] = "boolean"; class2type["[object Number]"] = "number"; class2type["[object String]"] = "string"; class2type["[object Function]"] = "function"; class2type["[object Array]"] = "array"; class2type["[object Date]"] = "date"; class2type["[object RegExp]"] = "regexp"; class2type["[object Object]"] = "object"; var ReadyObj = { // DOM ? true, . isReady: false, // , , . readyWait: 1, // ( ) holdReady: function(hold) { if (hold) { ReadyObj.readyWait++; } else { ReadyObj.ready(true); } }, // , DOM ready: function(wait) { // , DOMready/load if ((wait === true && !--ReadyObj.readyWait) || (wait !== true && !ReadyObj.isReady)) { // , body , , IE . if (!document.body) { return setTimeout(ReadyObj.ready, 1); } // DOM ReadyObj.isReady = true; // DOM Ready , , , if (wait !== true && --ReadyObj.readyWait > 0) { return; } // , readyList.resolveWith(document, [ReadyObj]); // //if ( ReadyObj.fn.trigger ) { // ReadyObj( document ).trigger( "ready" ).unbind( "ready" ); //} } }, bindReady: function() { if (readyList) { return; } readyList = ReadyObj._Deferred(); // , $(document).ready() // , . if (document.readyState === "complete") { // , return setTimeout(ReadyObj.ready, 1); } // Mozilla, Opera webkit nightlies if (document.addEventListener) { // callback document.addEventListener("DOMContentLoaded", DOMContentLoaded, false); // window.onload, window.addEventListener("load", ReadyObj.ready, false); // IE } else if (document.attachEvent) { // , // , , iframes document.attachEvent("onreadystatechange", DOMContentLoaded); // window.onload, window.attachEvent("onload", ReadyObj.ready); // IE, frame // , var toplevel = false; try { toplevel = window.frameElement == null; } catch (e) {} if (document.documentElement.doScroll && toplevel) { doScrollCheck(); } } }, _Deferred: function() { var // callback callbacks = [], // stored [ context , args ] fired, // , firing, // , cancelled, // deferred = { // done( f1, f2, ...) done: function() { if (!cancelled) { var args = arguments, i, length, elem, type, _fired; if (fired) { _fired = fired; fired = 0; } for (i = 0, length = args.length; i < length; i++) { elem = args[i]; type = ReadyObj.type(elem); if (type === "array") { deferred.done.apply(deferred, elem); } else if (type === "function") { callbacks.push(elem); } } if (_fired) { deferred.resolveWith(_fired[0], _fired[1]); } } return this; }, // resolveWith: function(context, args) { if (!cancelled && !fired && !firing) { // , args = args || []; firing = 1; try { while (callbacks[0]) { callbacks.shift().apply(context, args); //shifts a callback, and applies it to document } } finally { fired = [context, args]; firing = 0; } } return this; }, // resolve: function() { deferred.resolveWith(this, arguments); return this; }, // ? isResolved: function() { return !!(firing || fired); }, // cancel: function() { cancelled = 1; callbacks = []; return this; } }; return deferred; }, type: function(obj) { return obj == null ? String(obj) : class2type[Object.prototype.toString.call(obj)] || "object"; } } // DOM Internet Explorer function doScrollCheck() { if (ReadyObj.isReady) { return; } try { // IE, // http://javascript.nwbox.com/IEContentLoaded/ document.documentElement.doScroll("left"); } catch (e) { setTimeout(doScrollCheck, 1); return; } // ReadyObj.ready(); } // document ready if (document.addEventListener) { DOMContentLoaded = function() { document.removeEventListener("DOMContentLoaded", DOMContentLoaded, false); ReadyObj.ready(); }; } else if (document.attachEvent) { DOMContentLoaded = function() { // , body , , IE (ticket #5443). if (document.readyState === "complete") { document.detachEvent("onreadystatechange", DOMContentLoaded); ReadyObj.ready(); } }; } function ready(fn) { // "" ReadyObj.bindReady(); var type = ReadyObj.type(fn); // callback' readyList.done(fn); // ReadyList _Deferred() } return ready; })(); DOMContentLoaded document . IE9+. document.addEventListener('DOMContentLoaded', function() { // }, false); readystatechange document readyState . , IE4+. document.onreadystatechange = function(){ if(document.readyState === 'complete'){ // } }; <script></script> body . DOM, . <body> <div>...</div> <script> // </script> </body> body . function onload() { // }; <body> ... <script> onload(); </script> </body> body onload . function myFunc() { // }; <body onload="myFunc()">...</body> readystatechange , . /** DOM */ document.onreadystatechange = function(){ if(document.readyState === 'complete'){ selector(); }; }; /** */ return selector; __proto__ , jQuery . __proto__ IE11+. . if (array.__proto__) { array.__proto__ = jQuery.prototype; } else { for (var param in jQuery.prototype) { array[param] = jQuery.prototype[param]; }; }; /** β */ var jQuery = function (selector, context) { return new jQuery.prototype.init(selector, context); }; /** */ jQuery.prototype = { constructor: jQuery }; /** */ var init = jQuery.prototype.init = function (selector, context) { /** , */ var array = []; /** * proto * , * * * jQuery */ /** __proto__ * IE11+ * */ if (array.__proto__) { array.__proto__ = jQuery.prototype; } else { for (var param in jQuery.prototype) { array[param] = jQuery.prototype[param]; }; }; /** , * * HTML */ if (typeof selector === 'string') { /** , HTML */ if (selector[0] === "<" && selector[selector.length - 1] === ">" && selector.length >= 3) { /** HTML */ jQuery.merge(array, jQuery.parseHTML(selector, context && context.nodeType ? context.ownerDocument || context : document, true)); /** , context * . , * DOM . */ if ({}.toString.call(context) === '[object Object]') { for (var i = 0; i < array.length; i++) { for (var argument in context) { array.setAttribute(argument, context[argument]); }; }; }; /** */ return array; /** HTML, */ } else { /** * , context * , * selector */ /** context */ if (context && context.nodeType) { /** */ var Elements = context.querySelectorAll(selector); /** */ return jQuery.merge(array, Elements); /** context */ } else if ({}.toString.call(context) === '[object HTMLCollection]' || {}.toString.call(context) === '[object NodeList]') { /** * * */ for (var i = 0; i < context.length; i++) { /** */ var Elements = context[i].querySelectorAll(selector); /** */ jQuery.merge(array, Elements); }; /** */ return array; /** context */ } else if (typeof context === 'string') { /** * */ var Parents = document.querySelectorAll(context); /** * * */ for (var i = 0; i < Parents.length; i++) { /** */ var Elements = Parents[i].querySelectorAll(selector); /** */ jQuery.merge(array, Elements); }; /** */ return array; /** * , * */ } else { /** */ var Elements = document.querySelectorAll(selector); /** */ return jQuery.merge(array, Elements); } }; /** , DOM */ } else if (selector.nodeType) { /** */ array[0] = selector; /** */ return array; /** * * */ } else if ({}.toString.call(selector) === '[object Array]') { /** */ jQuery.merge(array, selector); /** */ return array; /** * , * */ } else if ({}.toString.call(selector) === '[object Object]') { /** */ array[0] = selector; /** */ return array; /** , ? */ } else if ({}.toString.call(selector) === '[object HTMLCollection]' || {}.toString.call(selector) === '[object NodeList]') { /** */ jQuery.merge(array, selector); /** */ return array; /** β */ } else if ({}.toString.call(selector) === '[object Function]') { /** DOM */ document.onreadystatechange = function(){ if(document.readyState === 'complete'){ selector(); }; }; /** */ return selector; /** , */ } else { return array; } }; jQuery.merge = function (first, second) { var len = +second.length, /** second.length , , */ j = 0, i = first.length; /** */ for (; j < len; j++) { /** * * * */ first[i++] = second[j]; } /** */ first.length = i; /** */ return first; }; jQuery.parseHTML = function (data, context, keepScripts) { /** , */ if (typeof data !== 'string') { return []; } /** * context * keepScripts, * true/false */ if (typeof context === 'boolean') { keepScripts = context; context = false; }; var DOM, DOMList; if (!context || context === document) { /** HTML */ DOM = document.implementation.createHTMLDocument() || new DOMParser().parseFromString('', 'text/html'); /** HTML */ DOM.body.innerHTML = data; /** */ DOMList = DOM.body.childNodes; } else if (context.nodeType) { /** , */ DOM = document.createElement('div'); /** */ context.appendChild(DOM); /** */ DOM.innerHTML = data; /** */ DOMList = DOM.childNodes; /** DOM */ DOM.parentNode.removeChild(DOM); }; /** , */ if (keepScripts === true) { /** */ var scripts = DOM.scripts || DOM.querySelectorAll('script'); /** */ if (scripts.length > 0) { /** */ for (var i = 0; i < scripts.length; i++) { /** */ var script = document.createElement('script'); /** */ script.innerHTML = scripts[i].innerHTML; if (scripts[i].attributes) script.attributes = scripts[i].attributes; /** HEAD */ document.head.appendChild(script); /** HEAD */ script.parentNode.removeChild(script); }; }; }; /** */ return (function () { var array = []; for (var i = 0; i < DOMList.length; i++) { array[array.length] = DOMList[i]; }; return array; })(); }; jQuery.prototype.myFunction = function () {...}; Source: https://habr.com/ru/post/335958/
All Articles