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