JQuery source code analysis-03 construct a jQuery object-tool function. For more information, see. Author: nuysoft/high cloud QQ: 47214707 EMail: nuysoft@gmail.com
Disclaimer: This article is an original article. If you need to reprint it, please indicate the source and retain the original article link.
Read, write, or something wrong. Please tell me more about the progress. The PDF in this chapter has been written and published.
For the directory of the jQuery source code analysis series, see examples.
3.4 other static tool Functions
The Code is as follows:
// Extended tool Functions
JQuery. extend ({
// Release $'s jQuery Control
// Many JavaScript libraries use $ as the name of a function or variable, as is jQuery.
// In jQuery, $ is just the alias of jQuery, so all functions can be guaranteed even if $ is not used.
// If we need to use another JavaScript library other than jQuery, we can return control to the library by calling $. noConflict.
// By passing the parameter true to this method, we can return the control of $ and jQuery to another JavaScript library.
NoConflict: function (deep ){
// Hand over the control of $
If (window. $ === jQuery ){
Window. $ =_$;
}
// Hand over control of jQuery
If (deep & window. jQuery === jQuery ){
Window. jQuery = _ jQuery;
}
Return jQuery;
},
// Is the DOM ready to be used? Set to true once it occurs.
IsReady: false,
// A counter to track how many items to wait for before
// The ready event fires. See #6781
// A counter used to track the number of waits before the ready event starts
ReadyWait: 1,
// Hold (or release) the ready event
// Wait or trigger
HoldReady: function (hold ){
If (hold ){
JQuery. readyWait ++;
} Else {
JQuery. ready (true );
}
},
// Handle when the DOM is ready
// Handle for document loading
Ready: function (wait ){
// Either a released hold or an DOMready/load event and not yet ready
//
If (wait === true &&! -- JQuery. readyWait) | (wait! = True &&! JQuery. isReady )){
// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443 ).
// Ensure that document. body exists
If (! Document. body ){
Return setTimeout (jQuery. ready, 1 );
}
// Remember that the DOM is ready
JQuery. isReady = true;
// If a normal DOM Ready event fired, decrement, and wait if need be
If (wait! = True & -- jQuery. readyWait> 0 ){
Return;
}
// If there are functions bound, to execute
ReadyList. resolveWith (document, [jQuery]);
// Trigger any bound ready events
If (jQuery. fn. trigger ){
JQuery (document). trigger ("ready"). unbind ("ready ");
}
}
},
// Initialize the readyList event processing function queue
// Compatible with the differences between events bound to different views
BindReady: function (){
If (readyList ){
Return;
}
ReadyList = jQuery. _ Deferred ();
// Catch cases where $ (document). ready () is called after
// Browser event has already occurred.
If (document. readyState = "complete "){
// Handle it asynchronously to allow scripts the opportunity to delay ready
Return setTimeout (jQuery. ready, 1 );
}
// Mozilla, Opera and webkit nightlies currently support this event
// Compatible event, by detecting the functional features of the browser, rather than sniffing the browser
If (document. addEventListener ){
// Use the handy event callback
// Use a fast loading completion event
Document. addEventListener ("DOMContentLoaded", DOMContentLoaded, false );
// A fallback to window. onload, that will always work
// Register the window. onload callback function
Window. addEventListener ("load", jQuery. ready, false );
// If IE event model is used
} Else if (document. attachEvent ){
// Ensure firing before onload,
// Maybe late but safe also for iframes
// Make sure that onreadystatechange is triggered before onload, which may be slower but safer for iframes
Document. attachEvent ("onreadystatechange", DOMContentLoaded );
// A fallback to window. onload, that will always work
// Register the window. onload callback function
Window. attachEvent ("onload", jQuery. ready );
// If IE and not a frame
// Continually check to see if the document is ready
Var toplevel = false;
Try {
Toplevel = window. frameElement = null;
} Catch (e ){}
If (document.doc umentElement. doScroll & toplevel ){
DoScrollCheck ();
}
}
},
// See test/unit/core. js for details concerning isFunction.
// Since version 1.3, DOM methods and functions like alert
// Aren't supported. They return false on IE (#2968 ).
// Function?
IsFunction: function (obj ){
Return jQuery. type (obj) = "function ";
},
// Array or not
// If the browser has built-in Array. isArray implementation, use the browser's own implementation method,
// Otherwise, convert the object to String to see if it is "[object Array]".
IsArray: Array. isArray | function (obj ){
Return jQuery. type (obj) = "array ";
},
// A crude way of determining if an object is a window
// You can determine whether the setInterval attribute is a window object.
IsWindow: function (obj ){
Return obj & typeof obj = "object" & "setInterval" in obj;
},
// Whether it is a reserved word NaN
IsNaN: function (obj ){
// Equals null or not a number or calls window. isNaN to determine
Return obj = null |! Rdigit. test (obj) | isNaN (obj );
},
// Obtain the object type
Type: function (obj ){
// Create an object using the core API without the new Keyword
// Normal functions do not work
// Call the Object. prototype. toString method to generate a string in the format of "[object Xxx ]"
// Class2type ["[object" + name + "]"] = name. toLowerCase ();
Return obj = null?
String (obj ):
Class2type [toString. call (obj)] | "object ";
},
// Check whether obj is a pure Object (an Object created through "{}" or "new Object)
// Console.info ($. isPlainObject ({}); // true
// Lele.info ($. isPlainObject (''); // false
// Console.info ($. isPlainObject (document. location); // true
// Console.info ($. isPlainObject (document); // false
// Lele.info ($. isPlainObject (new Date (); // false
// Console.info ($. isPlainObject (); // false
// IsPlainObject analysis and reconstruction http://www.jb51.net/article/25047.htm
// An http://www.cnblogs.com/phpmix/articles/1733599.html for jQuery. isPlainObject ()
IsPlainObject: function (obj ){
// Must be an Object.
// Because of IE, we also have to check the presence of the constructor property.
// Make sure that DOM nodes and window objects don't pass through, as well
// It must be an object
// Because an Invalid Pointer exception is thrown in IE8, the constructor attribute must be checked.
// DOM node and window object, return false
// If obj does not exist or is not of the object type, DOM node, or widnow object, false is directly returned.
// Test the following three possible conditions:
// JQuery. type (obj )! = "Object" type is not an object, ignore
// Obj. nodeType indicates that the DOM node is not a pure object.
// JQuery. isWindow (obj) considers window as not a pure object
If (! Obj | jQuery. type (obj )! = "Object" | obj. nodeType | jQuery. isWindow (obj )){
Return false;
}
// Not own constructor property must be Object
// Test the constructor attributes
// Constructor has constructor, but is not its own attribute (inherited by prototype ),
If (obj. constructor &&
! HasOwn. call (obj, "constructor ")&&
! HasOwn. call (obj. constructor. prototype, "isPrototypeOf ")){
Return false;
}
// Own properties are enumerated firstly, so to speed up,
// If last one is own, then all properties are own.
Var key;
For (key in obj ){}
// Key = undefined and no attributes exist. It is regarded as a simple pure object.
// HasOwn. call (obj, key) the attribute key is not empty, and the object of the attribute key itself (that is, it is not inherited by prototype)
Return key = undefined | hasOwn. call (obj, key );
},
// Whether the object is null
IsEmptyObject: function (obj ){
For (var name in obj ){
Return false;
}
Return true;
},
// Throw an exception
Error: function (msg ){
Throw msg;
},
// Parse JSON
// ParseJSON converts a string into a JSON object.
// We generally use eval. ParseJSON encapsulates this operation, but eval is used as the final method.
// Because JSON serialization and deserialization APIs are added to the latest JavaScript standard.
// If the browser supports this standard, the two APIs are implemented using Native Code in the JS engine, and the efficiency is certainly much higher than that of eval.
// Currently, both Chrome and Firefox4 support this API.
ParseJSON: function (data ){
If (typeof data! = "String" |! Data ){
Return null;
}
// Make sure leading/trailing whitespace is removed (IE can't handle it)
Data = jQuery. trim (data );
// Attempt to parse using the native JSON parser first
// Native json api. Deserialization is JSON. stringify (object)
If (window. JSON & window. JSON. parse ){
Return window. JSON. parse (data );
}
// Make sure the incoming data is actual JSON
// Logic borrowed from http://json.org/json2.js
//... Check the validity of the string roughly.
If (rvalidchars. test (data. replace (rvalidescape ,"@")
. Replace (rvalidtokens, "]")
. Replace (rvalidbraces ,""))){
Return (new Function ("return" + data ))();
}
JQuery. error ("Invalid JSON:" + data );
},
// Cross-browser xml parsing
// (Xml & tmp used internally)
// Parse XML cross-browser
// ParseXML functions are encapsulated by standard APIs and IE.
// The standard API is a DOMParser object.
// IE uses the ActiveXObject object of Microsoft. XMLDOM.
ParseXML: function (data, xml, tmp ){
If (window. DOMParser) {// Standard XML Parser
Tmp = new DOMParser ();
Xml = tmp. parseFromString (data, "text/xml ");
} Else {// XML Parser for IE
Xml = new ActiveXObject ("Microsoft. XMLDOM ");
Xml. async = "false ";
Xml. loadXML (data );
}
Tmp = xml.doc umentElement;
If (! Tmp |! Tmp. nodeName | tmp. nodeName = "parsererror "){
JQuery. error ("Invalid XML:" + data );
}
Return xml;
},
// No operation function
Noop: function (){},
// Evaluates a script in a global context
// Workarounds based on findings by Jim Driscoll
// Http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
// The globalEval function loads a script into the global context (window.
// You can use window.exe cScript in IE.
// Eval is required for other browsers.
// Because the entire jQuery code is an anonymous function, the current context is jQuery. To set the context to window, use globalEval.
GlobalEval: function (data ){
// Data is not empty
If (data & rnotwhite. test (data )){
// We use execScript on Internet Explorer
// We use an anonymous function so that context is window
// Rather than jQuery in Firefox
(Window.exe cScript | function (data ){
Window ["eval"]. call (window, data );
}) (Data );
}
},
// Determine whether the node name is the same
NodeName: function (elem, name ){
// Case insensitive
Return elem. nodeName & elem. nodeName. toUpperCase () === name. toUpperCase ();
},
// Args is for internal usage only
// Traverse objects or Arrays
Each: function (object, callback, args ){
Var name, I = 0,
Length = object. length,
IsObj = length = undefined | jQuery. isFunction (object );
// If The args parameter exists, call apply and set the context to the object Currently traversed. The args
If (args ){
If (isObj ){
For (name in object ){
If (callback. apply (object [name], args) === false ){
Break;
}
}
} Else {
For (; I <length ;){
If (callback. apply (object [I ++], args) === false ){
Break;
}
}
}
// A special, fast, case for the most common use of each
// If args is not set, call is called. The context is set to the object Currently traversed, and the parameters are set to key/index and value.
} Else {
If (isObj ){
For (name in object ){
If (callback. call (object [name], name, object [name]) === false ){
Break;
}
}
} Else {
For (; I <length ;){
If (callback. call (object [I], I, object [I ++]) === false ){
Break;
}
}
}
}
Return object;
},
// Use native String. trim function wherever possible
// Use the local String. trim method as much as possible. Otherwise, the leading space is filtered first, and then the Ending Space is filtered.
Trim: trim?
Function (text ){
Return text = null?
"":
Trim. call (text );
}:
// Otherwise use our own trimming functionality
Function (text ){
Return text = null?
"":
Text. toString (). replace (trimLeft, ""). replace (trimRight ,"");
},
// Results is for internal usage only
// Convert a pseudo array to an array
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)
// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
// There are a lot of browser compatibility tests, which really hurt
Var type = jQuery. type (array );
// Test: whether the length attribute, String, function, and regular expression are available
// Not an array, not even a pseudo Array
If (array. length = null
| Type = "string"
| Type = "function"
| Type = "regexp"
| JQuery. isWindow (array )){
Push. call (ret, array );
} Else {
// $. Type ($ ('P') // object
JQuery. merge (ret, array );
}
}
Return ret;
},
//
InArray: function (elem, array ){
// Whether there is a localized Array. prototype. indexOf
If (indexOf ){
// Directly call Array. prototype. indexOf
Return indexOf. call (array, elem );
}
// Traverse the array to check whether there are completely equal elements and return the subscript
// Tips for loop: store array. length in the length variable, which can reduce the number of scope searches.
For (var I = 0, length = array. length; I <length; I ++ ){
If (array [I] === elem ){
Return I;
}
}
// If-1 is returned, it indicates it is not in the array
Return-1;
},
// Merge the array second into array first
Merge: function (first, second ){
Var I = first. length ,//
J = 0;
// If the length attribute of second is of the Number type, process second as an array.
If (typeof second. length = "number "){
For (var l = second. length; j <l; j ++ ){
First [I ++] = second [j];
}
} Else {
// Traverse second and add non-undefined values to first
While (second [j]! = Undefined ){
First [I ++] = second [j ++];
}
}
// Modify the length attribute of first because first may not be a real array.
First. length = I;
Return first;
},
// Filter the array and return a new array. The value is retained when callback returns true. If inv is true, callback returns false.
Grep: function (elems, callback, inv ){
Var ret = [], retVal;
Inv = !! Inv;
// Go through the array, only saving the items
// That pass the validator function
// Traverses the array and only retains the elements that pass the verification function callback.
For (var I = 0, length = elems. length; I <length; I ++ ){
// Here, the callback parameter list is: value, index, consistent with the each habit
RetVal = !! Callback (elems [I], I );
// Whether to reverse select
If (inv! = RetVal ){
Ret. push (elems [I]);
}
}
Return ret;
},
// Arg is for internal usage only
// Convert the elements/attributes of an array or elems object into a new array
Map: function (elems, callback, arg ){
Var value, key, ret = [],
I = 0,
Length = elems. length,
// Jquery objects are treated as arrays
// Check whether elems is a pseudo Array
// 1. Treat jQuery objects as Arrays
// 2. Check whether the length attribute exists. length is equal to 0, or whether the first and last elements exist, or jQuery. isArray returns true.
IsArray = elems instanceof jQuery
| Length! = Undefined & typeof length = "number"
& (Length> 0 & elems [0] & elems [length-1]) | length = 0 | jQuery. isArray (elems ));
// It is the difference between arrays or objects. Only the Traversal method is different and there is no other difference.
// Go through the array, translating each of the items to their
// Traverses the array and calls callback for each element. The returned value is not null and stored in ret.
If (isArray ){
For (; I <length; I ++ ){
// Run callback. The parameters are value, index, and arg.
Value = callback (elems [I], I, arg );
// If null is returned, it is ignored (the function without return value will return undefined)
If (value! = Null ){
Ret [ret. length] = value;
}
}
// Go through every key on the object,
// Traverses the object and calls callback for each attribute. The returned value is not null and stored in ret.
} Else {
For (key in elems ){
// Run callback. The parameters are value, key, and arg.
Value = callback (elems [key], key, arg );
// Same as above
If (value! = Null ){
Ret [ret. length] = value;
}
}
}
// Flatten any nested arrays
// Flatten the nested Array
// Concat:
// If an item is an array, add its content to the end.
// If the project is not an array, add it as a single array element to the end of the array.
Return ret. concat. apply ([], ret );
},
// A global GUID counter for objects
Guid: 1,
// Bind a function to a context, optionally partially applying any
// Arguments.
// Proxy method: Specify the context (this) for fn)
// JQuery. proxy (function, context)
// JQuery. proxy (context, name)
Proxy: function (fn, context ){
// If context is a string, set context to fn and fn to fn [context]
// Set the context of the fn context method to fn (which is not the default ??? TODO)
If (typeof context = "string "){
Var tmp = fn [context];
Context = fn;
Fn = tmp;
}
// Quick check to determine if target is callable, in the spec
// This throws a TypeError, but we will just return undefined.
// Quickly test whether the fn is callable (that is, a function). In the instructions of this document, a TypeError is thrown,
// But only undefined is returned here
If (! JQuery. isFunction (fn )){
Return undefined;
}
// Simulated bind
Var args = slice. call (arguments, 2), // remove fn, context from the parameter list
Proxy = function (){
// Set the context to context and parameters.
Return fn. apply (context, args. concat (slice. call (arguments )));
};
// Set the guid of unique handler to the same of original handler, so it can be removed
// Unify the guid so that the proxy can be removed
Proxy. guid = fn. guid = fn. guid | proxy. guid | jQuery. guid ++;
Return proxy;
},
// Mutifunctional method to get and set values to a collection
// The value/s can be optionally by executed if its a function
// A multi-function that reads or sets the property value of a set. If the value is a function, it is executed.
// Fn: jQuery.fn.css, jQuery. fn. attr, jQuery. fn. prop
Access: function (elems, key, value, exec, fn, pass ){
Var length = elems. length;
// Setting many butes
// Iteration if multiple attributes exist
If (typeof key = "object "){
For (var k in key ){
JQuery. access (elems, k, key [k], exec, fn, value );
}
Return elems;
}
// Setting one attribute
// Set only one attribute
If (value! = Undefined ){
// Optionally, function values get executed if exec is true
Exec =! Pass & exec & jQuery. isFunction (value );
For (var I = 0; I <length; I ++ ){
Fn (elems [I], key, exec? Value. call (elems [I], I, fn (elems [I], key): value, pass );
}
Return elems;
}
// Getting an attribute
// Read attributes
Return length? Fn (elems [0], key): undefined;
},
// Obtain convenient functions for the current time
Now: function (){
Return (new Date (). getTime ();
},
// Use of jQuery. browser is frowned.
// More details: http://docs.jquery.com/Utilities/jQuery.browser
// Do not approve of jQuery. browser. jQuery. support is recommended.
// Information of the browser in use by Navigator
// Navigator. userAgent is a read-only string that declares the value of the user proxy header used by the browser for HTPP requests.
UaMatch: function (ua ){
Ua = ua. toLowerCase ();
// Match each browser in sequence
Var match = rwebkit.exe c (ua) |
Ropera.exe c (ua) |
Rmsie.exe c (ua) |
Ua. indexOf ("compatible") <0 & rmozilla.exe c (ua) |
[];
// Match [1] | ""
// When match [1] is false (null String, null, undefined, 0, etc.), the default value is ""
// Match [2] | "0"
// When match [2] is false (null String, null, undefined, 0, etc.), the default value is "0"
Return {browser: match [1] | "", version: match [2] | "0 "};
},
// Create a new jQuery copy. The attributes and methods of the copy can be changed, but they do not affect the original jQuery object.
// There are two usage methods:
// 1. Override the jQuery method without damaging the original method
// 2. encapsulation to avoid namespace conflicts and can be used to develop jQuery plug-ins
// It is worth noting that the jQuery. sub () function does not provide true isolation, and all attributes and methods still point to the original jQuery
// If you use this method to develop plug-ins, we recommend that you prioritize the jQuery UI widget project.
Sub: function (){
Function jQuerySub (selector, context ){
Return new jQuerySub. fn. init (selector, context );
}
JQuery. extend (true, jQuerySub, this); // copy all jQuery attributes and methods to jQuerySub.
JQuerySub. superclass = this;
JQuerySub. fn = jQuerySub. prototype = this ();//
JQuerySub. fn. constructor = jQuerySub;
JQuerySub. sub = this. sub;
JQuerySub. fn. init = function init (selector, context ){
If (context & context instanceof jQuery &&! (Context instanceof jQuerySub )){
Context = jQuerySub (context );
}
Return jQuery. fn. init. call (this, selector, context, rootjQuerySub );
};
JQuerySub. fn. init. prototype = jQuerySub. fn;
Var rootjQuerySub = jQuerySub (document );
Return jQuerySub;
},
// Browser type and version:
// $. Browser. msie/mozilla/webkit/opera
// $. Browser. version
// It is not recommended to sniff the browser type jQuery. browser, but to check the functional features of the browser jQuery. support
// JQuery. browser may be moved to a plug-in the future
Browser :{}
});