The overall jQuery framework is very complicated and not easy to understand. I have been studying this heavy and powerful framework in the past few days. The overall architecture of jQuery can be divided into: entry module, underlying module and functional module. Here, we take jquery-1.7.1 as an example for analysis.
The overall architecture of jquery
Analyzing the above code, we found that jquery adopts the writing method of anonymous function self-execution. The advantage of this is that it can effectively prevent the problem of namespace and variable pollution. Abbreviating the above code is:
Parameter window
The anonymous function passes in two parameters, one is window and the other is undefined. We know that variables in js have scope chains. The two variables passed in will become local variables of the anonymous function, and they will be accessed faster. By passing in the window object, the window object can be used as a local variable. Then, the parameters of the function also become local variables. When accessing the window object in jquery, there is no need to return the scope chain to the top-level scope, thus The window object can be accessed faster.
Parameter undefined
When js searches for a variable, the js engine will first search for the variable in the scope of the function itself. If it does not exist, it will continue to search upwards. If it is found, it will return the variable. If it cannot find it, it will return undefined. undefined is a property of the window object. By passing in the undefined parameter without assigning a value, the scope chain when searching for undefined can be shortened. Within the scope of a self-calling anonymous function, ensure that undefined is truly undefined. Because undefined can be overwritten and given a new value.
What is jquery.fn?
By analyzing the above code, we found that jQuery.fn is jQuery.prototype. The advantage of writing it this way is that it is shorter. Later, we saw that jquery simply used a $ symbol instead of jquery for simplicity. Therefore, when we use the jquery framework, we often use $(),
Constructor jQuery()
Image description
jQuery objects are not created through new jQuery, but through new jQuery.fn.init:
return new jQuery.fn.init( selector, context, rootjQuery );
}
A variable jQuery is defined here, and its value is the jQuery constructor, which is returned and assigned to the jQuery variable at line 955 (the top code)
jQuery.fn.init
jQuery.fn (line 97 above) is the prototype object of the constructor function jQuery(), and jQuery.fn.init() is the jQuery prototype method, which can also be called a constructor. Responsible for parsing the types of parameters selector and context and performing corresponding searches.
Parameter context: You can not pass it in, or you can pass it in a jQuery object, DOM element, or one of the ordinary js objects
Parameter rootjQuery: jQuery object containing the document object, used for situations such as document.getElementById() failure.
By default, the search for matching elements starts from the root element document object, that is, the search scope is the entire document tree, but you can also pass in the second parameter context to limit its search scope. For example:
The methods jQuery.extend(object) and jQuery.fn.extend(object) are used to merge two or more objects into the first object. The relevant source code is as follows (part):
jQuery.extend(object); Add a class method to the jQuery class, which can be understood as adding a static method. Such as:
Add a "static method" called add for jQuery, and then you can use this method where jQuery is introduced,
$.add(3,4); //return 7
jQuery.fn.extend(object), check out a code demonstration on the official website as follows:
<script><br>
jQuery.fn.extend({<br>
check: function() {<br>
return this.each(function() {<br>
This.checked = true;<br>
});<br>
},<br>
uncheck: function() {<br>
return this.each(function() {<br>
This.checked = false;<br>
});<br>
}<br>
});<br>
// Use the newly created .check() method<br>
$( "input[type='checkbox']" ).check();<br>
</script>
CSS selector engine Sizzle
It can be said that jQuery was born to operate DOM. The reason why jQuery is so powerful is due to the CSS selector engine Sizzle. The parsing rules quote an example from the Internet:
selector:"div > p div.aaron input[type="checkbox"]"
Parsing rules:
1 Follow from right to left
2 Take out the last token, such as [type="checkbox"]
matches: Array[3]
type : "ATTR"
Checkbox "]"
}
3 Filter type If type is > ~ empty, one of the four relationship selectors, then skip and continue filtering
4 until it matches one of ID, CLASS, and TAG, because in this way it can be obtained through the browser interface
5 At this time, the seed collection has value, which reduces the conditions for brush selection
6. If there are multiple matching seed collections, further filtering is required. Modify the selector selector: "div > p div.aaron [type="checkbox"]"
7 OK, jump to the next stage of the compilation function
deferred object
In the process of developing websites, we often encounter certain JavaScript operations that take a long time. Among them, there are both asynchronous operations (such as ajax reading server data) and synchronous operations (such as traversing a large array), and the results are not available immediately.
The usual approach is to specify callback functions for them. That is, specify in advance which functions should be called once they have finished running.However, jQuery is very weak when it comes to callback functions. In order to change this, the jQuery development team designed the deferred object.
To put it simply, the deferred object is jQuery’s callback function solution. In English, defer means "delay", so the meaning of a deferred object is to "delay" execution until a certain point in the future.
Review the traditional way of writing jQuery’s ajax operation:
After the $.ajax() operation is completed, if you are using a version of jQuery lower than 1.5.0, the XHR object will be returned and you cannot perform chain operations; if the version is higher than 1.5.0, the returned Deferred objects can be chained.
Now, the new way of writing is this:
Another great benefit of the deferred object is that it allows you to specify a callback function for multiple events, which is not possible with traditional writing.
Please look at the following code, which uses a new method $.when():
.done(function(){ alert("Haha, successful!"); })
.fail(function(){ alert("Error!"); });
The meaning of this code is to first perform two operations $.ajax("test1.html") and $.ajax("test2.html"). If both are successful, run the callback specified by done() function; if one fails or both fail, the callback function specified by fail() is executed.
Implementation principle of jQuery.Deferred(func)
Three callback function lists are maintained internally: success callback function list, failure callback function list, and message callback function list. Other methods operate and detect around these three lists.
Source code structure of jQuery.Deferred( func ):
Deferred: function( func ) {
// Success callback function list
var doneList = jQuery.Callbacks( "once memory" ),
// List of failure callback functions
failList = jQuery.Callbacks( "once memory" ),
// Message callback function list
progressList = jQuery.Callbacks( "memory" ),
// Initial state
state = "pending",
// Read-only copy of the asynchronous queue
promise = {
// done, fail, progress
// state, isResolved, isRejected
// then, always
// pipe
// promise
},
// Asynchronous queue
deferred = promise.promise({}),
key;
// Add methods to trigger success, failure, and message callback lists
for (key in lists) {
deferred[key] = lists[key].fire;
deferred[ key "With" ] = lists[ key ].fireWith;
}
// Add a callback function to set the status
deferred.done( function() {
state = "resolved";
}, failList.disable, progressList.lock )
.fail( function() {
state = "rejected";
}, doneList.disable, progressList.lock );
// If the function parameter func is passed in, it will be executed.
if ( func ) {
func.call(deferred, deferred);
}
// Return asynchronous queue deferred
},
}
Provides the ability to execute callback functions based on the state of one or more objects, typically based on an asynchronous queue with asynchronous events.
If multiple asynchronous queue objects are passed in, the method jQuery.when() returns a new read-only copy of the main asynchronous queue object. The read-only copy will track the final status of the passed asynchronous queue.
Once all asynchronous queues become successful, the success callback function of the "main" asynchronous queue is called;
If one of the asynchronous queues becomes failed, the failure callback function of the main asynchronous queue is called.
Image description
Asynchronous Queue Deferred
Decoupling asynchronous tasks and callback functions
Provide basic functions for ajax module, queue module and ready event.
Prototype properties and methods
Prototype properties and methods source code:
The selector attribute is used to record the selector expression when jQuery finds and filters DOM elements.
The attribute .length represents the number of elements in the current jquery object.
The method .size() returns the number of elements in the current jquery object. It is functionally equivalent to the attribute length, but length should be used first because it has no function call overhead.
.size() source code is as follows:
Method .toArray() converts the current jQuery object into a real array. The converted array contains all elements. The source code is as follows:
Method.get(index) returns the element at the specified position in the current jQuery object, or an array containing all elements. Its source
The code is as follows:
// Return a 'clean' array
This.toArray():
// Return just the object
( num < 0 ? this[ this.length num ] : this[ num ] );
},
First, it will be judged whether num is less than 0. If it is less than 0, the subscript will be recalculated using length num, and then the array access operator ([]) will be used to obtain the element at the specified position. This is a small method that supports negative subscripts. Tip; if it is greater than or equal to 0, directly return the element at the specified position.
Detailed explanation of the use of eg() and get(): Summary of common jquery methods and usage examples
Method .each() is used to iterate through the current jQuery object and execute the callback function on each element. Method.each() is implemented internally by simply calling the static method jQuery.each():
The callback function is triggered in the context where the current element is the context, that is, the keyword this always points to the current element, and return false in the callback function can terminate the traversal.
Method .map() iterates through the current jQuery object, executes the callback function on each element, and puts the return value of the callback function into a new jQuery object. This method is often used to get or set the value of a collection of DOM elements.
The prototype method .pushStack() creates a new empty jQuery object, then puts the collection of DOM elements into this jQuery object, and retains a reference to the current jQuery object.
The prototype method.pushStack() is one of the core methods, which provides support for the following methods:
jQuery object traversal: .eq(), .first(), .last(), .slice(), .map().
DOM search and filtering: .find(), .not(), .filter(), .closest(), .add(), .andSelf().
DOM traversal: .parent(), .parents(), .parentsUntil(), .next(), .prev(), .nextAll(), .prevAll(), .nextUnit(), .prevUnit() , .siblings(), .children(), .contents().
DOM insertion: jQuery.before(), jQuery.after(), jQuery.replaceWith(), .append(), .prepent(), .before(), .after(), .replaceWith().
Define method .push(elems, name, selector), which accepts 3 parameters:
Parameter elems: Array of elements (or array-like object) that will be put into the new jQuery object.
Parameter name: The name of the jQuery method that generates the element array elems.
Parameter selector: The parameter passed to the jQuery method, used to modify the prototype attribute.selector.
Method .end() ends the most recent filtering operation in the current chain and restores the matching elements to their previous state
Returns the previous jQuery object. If the attribute prevObect does not exist, an empty jQuery object is constructed and returned. The method .pushStack() is used to push into the stack, and the method .end() is used to pop out of the stack
Static properties and methods
The relevant source code is as follows:
未完待续、、、今天就先到这里了,下次补齐。别急哈小伙伴们