Detailed analysis of jquery's overall architecture and implementation example _ jquery-js tutorial

Source: Internet
Author: User
Learning Open-source frameworks, kids shoes are most interested in designing ideas and implementation skills. I recently studied jQuery source code to record my understanding and experiences on jquery. I will share with you that the right should be a reference. The overall jQuery framework is complex and hard to understand. Over the past few days, I have been studying this bulky and powerful framework. The overall architecture of jQuery can be divided into entry module, underlying module, and function module. Here, we take jquery-1.7.1 as an example to analyze.

Overall architecture of jquery

The Code is as follows:


16 (function (window, undefined ){
// Construct a jQuery object
22 var jQuery = (function (){
25 var jQuery = function (selector, context ){
27 return new jQuery. fn. init (selector, context, rootjQuery );
28 },
// A bunch of local variable declarations
97 jQuery. fn = jQuery. prototype = {
98 constructor: jQuery,
99 init: function (selector, context, rootjQuery ){...},
// A bunch of prototype attributes and Methods
319 };
322 jQuery. fn. init. prototype = jQuery. fn;
324 jQuery. extend = jQuery. fn. extend = function (){...};
388 jQuery. extend ({
// A bunch of static attributes and Methods
892 });
955 return jQuery;
957 })();
// Omitting the code of other modules...
9246 window. jQuery = window. $ = jQuery;
9266}) (window );

After analyzing the above Code, we found that jquery adopts the self-execution method of anonymous functions. The advantage of this method is that it can effectively prevent namespace and variable pollution. The code above is:

The Code is as follows:


(Function (window, undefined ){
Var jQuery = function (){}
//...
Window. jQuery = window. $ = jQuery;
}) (Window );

Parameter window

The anonymous function uploads two parameters, window and undefined. As we know, variables in js have a scope chain. The input of these two variables will become the local variables of anonymous functions, and the access speed will be faster. You can use the window object as a local variable by passing in the window object. Then, the parameters of the function are also changed to local variables. When you access the window object in jquery, you do not need to return the scope chain to the top-level scope to access the window object more quickly.

Parameter undefined

When js looks for a variable, the js engine first searches for the variable in the function's own scope. If it does not, it continues to look up. If it finds the variable, it returns the variable, undefined is returned if it cannot be found. Undefined is an attribute of the window object. It can shorten the scope chain of undefined search by passing in the undefined parameter without assigning a value. Make sure that undefined is really undefined within the scope of the self-called anonymous function. Because undefined can be rewritten, a new value is assigned.

What is jquery. fn?

The Code is as follows:


JQuery. fn = jQuery. prototype = {
Constructor: jQuery,
Init: function (selector, context, rootjQuery ){...},
// A bunch of prototype attributes and Methods
};

By analyzing the above Code, we found that jQuery. fn is jQuery. prototype. The advantage of writing this code is to be shorter. Later, we can see that jquery simply uses a $ symbol to replace jquery for simplicity. Therefore, $ () is often used in the use of jquery frameworks (),

Constructor jQuery ()

Image Description

The jQuery object is not created through new jQuery, but created through new jQuery. fn. init:

The Code is as follows:


Var jQuery = function (selector, context ){

Return new jQuery. fn. init (selector, context, rootjQuery );

}

A variable jQuery is defined here. Its value is the jQuery constructor. It is returned in the first line (the top code) and assigned to the jQuery variable.

JQuery. fn. init

JQuery. fn (line 97 above) is the prototype object of the constructor jQuery (). jQuery. fn. init () is a jQuery prototype method, which can also be called a constructor. Parses the selector and context parameters and performs corresponding searches.

Parameter context: either a jQuery object, DOM element, or a common js object
RootjQuery: contains the jQuery object of the document Object. It is used in situations such as document. getElementById () Failure in searching.

The Code is as follows:


JQuery. fn. init. prototype = jQuery. fn = jQuery. prototype
JQuery (selector [, context])

By default, the search for matching elements starts from the root element document object, that is, the search range is the entire document tree. However, you can pass in the second parameter context to limit the search range. For example:

The Code is as follows:


$ ('P. foo'). click (function (){
$ ('Span ', this). addClass ('bar'); // specifies the search range, that is, the context
});
JQuery. extend () and jQuery. fn. extend ()

The jQuery. extend (object) and jQuery. fn. extend (object) methods are used to merge two or more objects to the first object. The source code is as follows (partial ):

The Code is as follows:


JQuery. extend = jQuery. fn. extend = function (){
Var options, name, src, copy, copyIsArray, clone, // defines a set of local variables
Target = arguments [0] | | {},
I = 1,
Length = arguments. length,
Deep = false;

JQuery. extend (object); adding class methods to the jQuery class can be understood as adding static methods. For example:

The Code is as follows:


$. Extend ({
Add: function (a, B) {returna + B ;}
});

Add a "static method" for jQuery as add, and then you can use this method in the place where jQuery is introduced,

$. Add (3, 4); // return 7
JQuery. fn. extend (object). view the code demo on the official website as follows:

The Code is as follows:


Foo
Bar

Script
JQuery. fn. extend ({
Check: function (){
Return this. each (function (){
This. checked = true;
});
},
Uncheck: function (){
Return this. each (function (){
This. checked = false;
});
}
});
// Use the newly created. check () method
$ ("Input [type = 'checkbox']"). check ();
Script

CSS selector engine Sizzle

It can be said that jQuery was born to operate the DOM. The reason why jQuery is so powerful is that thanks to the CSS selector engine Sizzle, parsing Rules reference an instance on the Internet:

Selector: "p> p + p. aaron input [type =" checkbox "]"

Resolution rules:
1. Start from right to left
2. Retrieve the last token, for example, [type = "checkbox"].
{
Matches: Array [3]
Type: "ATTR"
Value: "[type ="
Checkbox "]"
}
3. If the filter type is> + ~ If either of the four relationship selectors is null, skip and continue filtering.
4. It is not until it is matched with ID, CLASS, or TAG, because it can be obtained through the browser interface.
5 at this time, seed has a value in the seed collection. In this way, the selection condition is reduced to a small value.
6. If there are multiple matched seed collections, further filtering is required. Modify the selector: "p> p + p. aaron [type =" checkbox "]"
7 OK, jump to the compile function of the next stage

Deferred object

During website development, we often encounter some javascript operations that take a long time. Both asynchronous operations (for example, ajax reading server data) and synchronous operations (for example, traversing a large array) do not result immediately.

The usual practice is to specify the callback function for them ). Which functions should be called once they are finished.

However, jQuery has very weak functions in callback functions. To change this, the jQuery development team designed the deferred object.

Put simply, the deferred object is jQuery's callback function solution. In English, defer means "delay", so the deferred object means "delay" to a certain point in the future.

Let's review the traditional jQuery ajax operations:

The Code is as follows:


$. Ajax ({
Url: "test.html ",
Success: function (){
Alert ("Haha, success! ");
},
Error: function (){
Alert ("error! ");
}
});


In the code above, $. ajax () accepts an object parameter. This object contains two methods: The success method specifies the callback function after the operation is successful, and the error method specifies the callback function after the operation fails.

$. After ajax () is completed, if jQuery of version 1.5.0 or earlier is used, the returned XHR object cannot be chained. If jQuery of version 1.5.0 or later is returned, the deferred object is returned, you can perform chained operations.

Now, the new method is as follows:

The Code is as follows:


$. Ajax ("test.html ")
. Done (function () {alert ("Haha, success! ");})
. Fail (function () {alert ("error! ");});


Specify callback functions for multiple operations

Another major benefit of the deferred object is that it allows you to specify a callback function for multiple events, which is not traditionally written.

See the following code. It uses a new method $. when ():

The Code is as follows:


$. When ($. ajax ("test1.html"), $. ajax ("test2.html "))

. Done (function () {alert ("Haha, success! ");})

. Fail (function () {alert ("error! ");});

This Code indicates that two operations are performed first $. ajax ("test1.html") and $. ajax ("test2.html"). If all functions are successful, run the callback function specified by done (). if one or both fails, run fail () the specified callback function.

Implementation principle of jQuery. Deferred (func)

Three callback function lists are maintained internally: Successful callback function list, failed callback function list, and message callback function list. Other Methods perform operations and detection on these three lists.

Source code structure of jQuery. Deferred (func:

The Code is as follows:


JQuery. extend ({

Deferred: function (func ){
// List of successful callback Functions
Var doneList = jQuery. Callbacks ("once memory "),
// List of failed callback Functions
FailList = jQuery. Callbacks ("once memory "),
// Message callback function list
ProgressList = jQuery. Callbacks ("memory "),
// Initial status
State = "pending ",
// Read-only copy of asynchronous queue
Promise = {
// Done, fail, progress
// State, isResolved, isRejected
// Then, always
// Pipe
// Promise
},
// Asynchronous queue
Deferred = promise. promise ({}),
Key;
// Add the trigger success, failure, and message callback list
For (key in lists ){
Deferred [key] = lists [key]. fire;
Deferred [key + "With"] = lists [key]. fireWith;
}
// Add a callback function for the set status
Deferred. done (function (){
State = "resolved ";
}, FailList. disable, progressList. lock)
. Fail (function (){
State = "rejected ";
}, DoneList. disable, progressList. lock );
// If the function parameter func is input, run the command.
If (func ){
Func. call (deferred, deferred );
}

// Return the asynchronous queue deferred
Return deferred;
},
}

JQuery. when (deferreds)

It provides the function of executing callback functions based on the state of one or more objects, usually based on Asynchronous Queues with asynchronous events.

Usage of jQuery. when (deferreds)

If multiple asynchronous queue objects are input, the method jQuery. when () returns a read-only copy of a new primary asynchronous queue object. the read-only copy tracks the final state of the incoming asynchronous queue.

Once all asynchronous queues change to the successful status, the callback function of the "Main" Asynchronous queue is called successfully;

If one of the asynchronous queues changes to the failed status, the failure callback function of the primary asynchronous queue is called.

The Code is as follows:


/*
Request '/when. do? Method = when1 'Return {"when": 1}
Request '/when. do? Method = when2 'Return {"when": 2}
Request '/when. do? Method = when3 'Return {"when": 3}
*/
Var whenDone = function () {console. log ('done', arguments );},
WhenFail = function () {console. log ('fail ', arguments );};
$. When (
$. Ajax ('/when. do? Method = when1', {dataType: "json "}),
$. Ajax ('/when. do? Method = when2', {dataType: "json "}),
$. Ajax ('/when. do? Method = when3', {dataType: "json "})
). Done (whenDone). fail (whenFail );

Image Description

Asynchronous queue Deferred

Decoupling asynchronous tasks and callback Functions

Provides basic functions for ajax, queue, and ready events.

Prototype attributes and Methods

Source code of prototype attributes and methods:

The Code is as follows:


97 jQuery. fn = jQuery. prototype = {
98 constructor: jQuery,
99 init: function (selector, context, rootjQuery ){}
210 selector :"",
213 jquery: "1.7.1 ",
216 length: 0,
219 size: function (){},
223 toArray: function (){},
229 get: function (num ){},
241 pushStack: function (elems, name, selector ){},
270 each: function (callback, args ){},
274 ready: function (fn ){},//
284 eq: function (I ){},
291 first: function (){},
295 last: function (){},
299 slice: function (){},
304 map: function (callback ){},
310 end: function (){},
316 push: push,
317 sort: []. sort,
318 splice: []. splice
319 };

The selector attribute is used to record the selector expression when jQuery finds and filters DOM elements.
Attribute. length indicates the number of elements in the current jquery object.
Method. size () returns the number of elements in the current jquery object. The function is equivalent to the attribute length, but the length should be used first because it has no function call overhead.

. Size () source code is as follows:

The Code is as follows:


Size (): function (){
Return this. length;
}

Method. toArray () converts the current jQuery object to a real array. The converted array contains all elements. The source code is as follows:

The Code is as follows:


ToArray: function (){
Return slice. call (this );
},

Method. get (index) returns the elements at the specified position in the current jQuery object, or an array containing all elements. Its source
The Code is as follows:

The Code is as follows:


Get: function (num ){
Return num = null?

// Return a 'clean' array
This. toArray ():

// Return just the object
(Num <0? This [this. length + num]: this [num]);
},


If no parameter is input, it is called. toArray () returns an array containing lock elements. If the index parameter is specified, an independent element is returned. The index starts from 0 and supports negative numbers.

First, the system checks whether num is less than 0. If num is less than 0, it recalculates the subscript with length + num, and then uses the array access operator ([]) to obtain the element at the specified position, this is a small technique that supports negative subscripts. If it is greater than or equal to 0, an element at the specified position is directly returned.

How to Use eg () and get (): Jquery common methods and Examples

Method. each () is used to traverse the current jQuery object and execute the callback function on each element. Method. each () is implemented by calling the static method jQuery. each:

The Code is as follows:


Each: function (callback, args ){
Return jQuery. each (this, callback, args );
},

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. In the callback function, return false can terminate the traversal.

Method. map () traverses 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 obtain or set the value of the DOM element set.

The Code is as follows:


Map: function (callback ){
Return this. pushStack (jQuery. map (this, function (elem, I ){
Return callback. call (elem, I, elem );
}));
},

The prototype method pushStack () creates a new empty jQuery object, puts the DOM Element Set into this jQuery object, and retains references 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). It accepts three parameters:

Parameter elems: Put the element array (or class array object) of the new jQuery object ).

Parameter name: name of the jQuery method that generates the element array elems.

Parameter selector: The parameter passed to the jQuery method. It is used to modify the prototype attribute. selector.
Method. end () ends the latest filtering operation in the current chain and restores the matching element to the previous state.

The Code is as follows:


End: function (){
Return this. prevObject | this. constructor (null );
},

Returns the previous jQuery object. If the prevObect attribute does not exist, an empty jQuery object is constructed and returned. Method. pushStack () is used for inbound stack, method. end () is used for outbound Stack

Static attributes and Methods

The source code is as follows:

The Code is as follows:


388 jQuery. extend ({
389 noConflict: function (deep ){},
402 isReady: false,
406 readyWait: 1,
409 holdReady: function (hold ){},
418 ready: function (wait ){},
444 bindReady: function (){},
492 isFunction: function (obj ){},
496 isArray: Array. isArray | function (obj ){},
501 isWindow: function (obj ){},
505 isNumeric: function (obj ){},
509 type: function (obj ){},
515 isPlainObject: function (obj ){},
544 isEmptyObject: function (obj ){},
551 error: function (msg ){},
555 parseJSON: function (data ){},
581 parseXML: function (data ){},
601 noop: function (){},
606 globalEval: function (data ){},
619 camelCase: function (string ){},
623 nodeName: function (elem, name ){},
628 each: function (object, callback, args ){},
669 trim: trim? Function (text) {}: function (text ){},
684 makeArray: function (array, results ){},
702 inArray: function (elem, array, I ){},
724 merge: function (first, second ){},
744 grep: function (elems, callback, inv ){},
761 map: function (elems, callback, arg ){},
794 guid: 1,
798 proxy: function (fn, context ){},
825 access: function (elems, key, value, exec, fn, pass ){},
852 now: function (){},
858 uaMatch: function (ua ){},
870 sub: function (){},
891 browser :{}
892 });

It will be available soon, and today. Don't worry, friends

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.