I've been studying jQuery Source code , At first glance, the source code is confused and confused , It's really wonderful to really calm down and read it carefully , Its structure is clear , High cohesion 、 Low coupling , Excellent performance and convenient scalability , Browser compatibility ( Functional defects 、 Progressive enhancement ) Elegant processing power and Ajax All the thoughtful and powerful customization functions are amazing .

jQuery This is the overall structure of :

jQuery The overall architecture

differ jQuery The implementation of each module of the code is obscure ,jQuery The structure of the overall framework is very clear , It is roughly divided into modules as shown in the figure above according to the code text .

First look jQuery Source code can be confusing , because 9000 Line code feels endless , So it's very important to understand the author's writing ideas .

As a whole , I think jQuery It's using total -- branch Structure , although JavaScript Promotion mechanism with scope , however 9000 Multiple lines of code for mutual relevance , Doesn't mean that all variables have to be defined at the top . stay jQuery in , Only the whole situation will be used Variable 、 Regular expressions Defined at the beginning of the code , At the beginning of each module , It will also define some variables that will only be used in this module 、 Regular 、 Such method . So in the process of reading at the beginning, there will be many variables that can't understand its function , Regular , Method .

therefore , I think it's important to read the source code , Abandoning the process oriented way of thinking , Don't try to find out every sentence from top to bottom at the beginning . It's very likely that at first you got stuck in a strange method or variable , I would like to know the function of this method or variable , However, it may not be called until thousands of lines . If you go after this kind of word for word clear way , It's very likely that the enthusiasm of reading will be greatly affected after several times of hitting the wall .

It makes a lot of sense , Take it to the real text , Yes jQurey Some preparations for , Small details for analysis :

jQuery Closure structure

1
2
3
4
5
6
7
// Wrapped with a function field , It's a sandbox
// Right here. var Variables defined , Local variables belonging to this function field , Avoid polluting the whole situation
// The external variables required by the current sandbox are introduced through the function parameters
// As long as the consistency of the interface provided in the parameter pair is ensured , You can also replace this parameter as you like
( function (window, undefined) {
    // jQuery Code
})(window);

jQuery Concrete implementation , Are contained in a closure that immediately executes function construction , In order not to pollute the global scope , Exposed only at the back $ and jQuery this 2 Variables to the outside world , Try to avoid variable conflicts . There is another way of writing :

1
2
3
( function (window) {
    // JS Code
})(window, undefined);

The first way to write , That is to say jQuery Writing . What's the difference between them , When our code runs in an earlier environment (pre-ES5,eg. Internet Explorer 8),undefined Only a variable and its value can be overridden . Which means you can do this :

1
2
undefined = 42
console.log(undefined)  // 42

When using the first method , To make sure you need undefined Indeed. undefined.

In addition, we have to point out that ,jQuery Here is a detail about compression optimization , Use the first method , When the code is compressed ,window and undefined Can be compressed to 1 Letters and make sure they are window and undefined.

1
2
3
4
5
// Compression strategy
// w -> windwow , u -> undefined
( function (w, u) {
 
})(window);

jQuery nothing new structure

Think about using jQuery When , Instantiate a jQuery Object method :

1
2
3
4
5
6
// nothing new structure
$( '#test' ).text( 'Test' );
 
// You can also use it new
var  test =  new  $( '#test' );
test.text( 'Test' );

Most people use jQuery When I use the first none new Mode of construction , direct $('') Construct , This is also jQuery A very convenient place . When we use the first none new When constructing , Its essence is equivalent to new jQuery(), So in jQuery How is it realized internally ? have a look :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
( function (window, undefined) {
     var
     // ...
     jQuery =  function (selector, context) {
         // The jQuery object is actually just the init constructor 'enhanced'
         // Look here , Instantiation method jQuery() In fact, it calls its extended prototype method jQuery.fn.init
         return  new  jQuery.fn.init(selector, context, rootjQuery);
     },
 
     // jQuery.prototype That is jQuery The prototype of the , How to mount it , All generated jQuery Object use
     jQuery.fn = jQuery.prototype = {
         // Instantiation method , This method can be called jQuery public instance constructors
         init:  function (selector, context, rootjQuery) {
             // ...
         }
     }
     // That's the key , It's also very round.
     // jQuery Not used new The operator will jQuery Instantiation , Instead, call its function directly
     // To achieve this , that jQuery It's like a class , And return a correct instance
     // And the instance should be able to access correctly jQuery Properties and methods on class prototypes
     // jQuery The way to solve the problem is through prototype delivery , hold jQuery The prototype of jQuery.prototype.init.prototype
     // So the instance generated by this method this It still points to jQuery.fn, So it can be accessed correctly jQuery Properties and methods on class prototypes
     jQuery.fn.init.prototype = jQuery.fn;
 
})(window);

Most people at first glance  jQuery.fn.init.prototype = jQuery.fn This sentence will be stuck , It is very puzzling. . But this really is jQuery What's wonderful about . It's important to understand these sentences , Point by point :

1) First of all, make it clear , Use $('xxx') This way of instantiation , Its internal call is  return new jQuery.fn.init(selector, context, rootjQuery) This sentence , That is to say, the construction instance is given to  jQuery.fn.init() Method to complete .

2) take jQuery.fn.init Of prototype Property is set to jQuery.fn, So use new jQuery.fn.init() The prototype object of the generated object is jQuery.fn , So mount to jQuery.fn The above function is equivalent to mounting to jQuery.fn.init() Generated jQuery On the object , All use  new jQuery.fn.init()  Generated objects can also access  jQuery.fn All prototyping methods on .

3) That is to say, the instantiation method has such a relationship chain

  • jQuery.fn.init.prototype = jQuery.fn = jQuery.prototype ;
  • new jQuery.fn.init() amount to new jQuery() ;
  • jQuery() The return is new jQuery.fn.init(), and var obj = new jQuery(), So this 2 It's equivalent , So we can have none new Instantiation jQuery object .

jQuery Method overloading

jQuery Another reason why the source code is difficult to read is , A lot of method overloading is used , But it's very convenient to use :

1
2
3
4
5
6
7
8
9
// obtain title The value of the property
$( '#id' ).attr( 'title' );
// Set up title The value of the property
$( '#id' ).attr( 'title' , 'jQuery' );
 
// obtain css The value of a property
$( '#id' ).css( 'title' );
// Set up css The value of a property
$( '#id' ).css( 'width' , '200px' );

Method overload is a method to achieve multiple functions , Often again get again set, Although it's hard to read , But from a practical point of view , That's why jQuery Why it's so popular , Most people use jQuery() The most common way to construct a method is to instantiate one directly jQuery object , But actually in its internal implementation , with 9 Different ways to reload scenes :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Accept a string , It contains the CSS Selectors
jQuery([selector,[context]])
// Incoming single DOM
jQuery(element)
// Pass in DOM Array
jQuery(elementArray)
// Pass in JS object
jQuery(object)
// Pass in jQuery object
jQuery(jQuery object)
// Afferent primitive HTML String to create DOM Elements
jQuery(html,[ownerDocument])
jQuery(html,[attributes])
// Null parameter passed in
jQuery()
// Bind a DOM Functions executed after document loading
jQuery(callback)

So when reading the source code , It's important to combine jQuery API To read , To find out how many functions the method overloads , At the same time, I want to say ,jQuery Some methods of source code are very long and tedious , because jQuery As a general framework , One method is compatible with many situations , It also allows users to pass in various parameters , The logic of internal processing is very complex , So when it comes to interpreting a method, it 's obviously difficult , Trying to jump out of the shell of the code itself , To think about what these complex logics are for or compatible with in a higher dimension , Overload or not , Why write like this , There must be different gains . secondly , That's why ,jQuery There are many sources that are compatible with lower versions of HACK Or code snippets with very obscure logic , Browser compatibility is such a big hole that it is extremely easy for a front-end engineer not to learn the essence of programming , So don't be too attached to some leftovers , Even if compatibility is important , We should also study and understand appropriately , Enough is enough .

   jQuery.fn.extend And  jQuery.extend

extend Method in jQuery Is a very important method ,jQuey It is used internally to extend static methods or instance methods , And we developed jQuery It is also used in plug-in development . But inside , Exist  jQuery.fn.extend and  jQuery.extend Two extend Methodical , And distinguish the two extend The way is to understand jQuery The key part of . Look at the conclusion first. :

1)jQuery.extend(object)  For extended jQuery Class itself , Add a new static method to the class ;

2)jQuery.fn.extend(object)  to jQuery Object add instance method , Through this extend New method added , Instantiated jQuery Objects can be used , Because it's mounted on jQuery.fn The method on the ( As mentioned above ,jQuery.fn = jQuery.prototype ).

Their official explanation is :

1)jQuery.extend(): Merge two or more objects into the first ,

2)jQuery.fn.extend(): Mount objects to jQuery Of prototype attribute , To expand a new jQuery Example method .

in other words , Use  jQuery.extend() Extended static method , We can use it directly $.xxx To call (xxx Is the name of the expanded method ),

While using  jQuery.fn.extend()  Extended case method , Need to use $().xxx call .

Long source code parsing , Click below to expand , You can also read here

+

It should be noted that  jQuery.extend = jQuery.fn.extend = function() {} , That is to say jQuery.extend Implementation and jQuery.fn.extend The same method is shared in the implementation of , But why can we achieve different functions , This is due to Javascript Powerful ( weird ?) Of this 了 .

1) stay  jQuery.extend() in ,this The direction is jQuery object ( Or rather, jQuery class ), So here we expand on jQuery On ;

2) stay  jQuery.fn.extend() in ,this The direction is  fn object , As mentioned earlier jQuery.fn = jQuery.prototype , That is to say, prototype method is added here , Object method .

   jQuery Chain call and backtracking of

The other one makes people like to use it jQuery Because of its chained call , The realization of this is very simple , Only in the return result of the method to implement the chain call , return this , You can implement the chain call .

Of course , In addition to chain calls ,jQuery It even allows backtracking , have a look :

1
2
// adopt end() Method to terminate the latest filtering operation in the current chain , Return to previous object collection
$( 'div' ).eq(0).show().end().eq(1).hide();

When chosen ('div').eq(0) Then use end() You can go back to the one you selected in the previous step jQuery object $('div'), Its internal implementation actually depends on the addition of prevObject This attribute :

jQuery Full chain call 、 Add stack 、 Backtracking  return this 、 return this.pushStack() 、return this.prevObject  Realization , Look at the source code implementation :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
jQuery.fn = jQuery.prototype = {
     // Will a DOM Element collection added to jQuery Stack
     // In this method jQuery Of DOM Frequently used in operation , If in parent(), find(), filter() in
     // pushStack() Method by changing a jQuery Object's prevObject Property to trace the DOM result set
     // When we call end() After the method , Internal return to current jQuery Object's prevObject attribute
     pushStack:  function (elems) {
         // Building a new jQuery object , Non parametric this.constructor(), Just return reference this
         // jQuery.merge hold elems Node merge to new jQuery object
         // this.constructor Namely jQuery Constructor for jQuery.fn.init, therefore this.constructor() Return to one jQuery object
         // because jQuery.merge The object returned by the function is the second function attached to the first , therefore ret Also a jQuery object , Here's why pushStack Discrepancy DOM Objects can also be used CSS Method to operate
         var  ret = jQuery.merge( this .constructor(), elems);
 
         // New for return jQuery Object add properties prevObject
         // So that's why prevObject Can get the reference of the previous collection
         ret.prevObject =  this ;
         ret.context =  this .context;
 
         // Return the newly-formed element set
         return  ret;
     },
     // Last object of backchained call
     end:  function () {
         // The key to backtracking is to return prevObject attribute
         // and prevObject Property saves the jQuery A collection of objects
         return  this .prevObject ||  this .constructor( null );
     },
     // Take the current jQuery Object number i individual
     eq:  function (i) {
         // jQuery Length of object collection
         var  len =  this .length,
             j = +i + (i < 0 ? len : 0);
 
         // utilize pushStack return
         return  this .pushStack(j >= 0 && j < len ? [ this [j]] : []);
     }, 
}

in general ,

1)end() Method returns prevObject attribute , This property records the previous operation's jQuery Object collection ;

2) and prevObject Attribute from pushStack() Method generation , This method takes a DOM Element collection added to jQuery A stack of internal management , By changing jQuery Object's prevObject Property to trace the DOM result set

3) When we call end() After the method , Internal return to current jQuery Object's prevObject attribute , Completing backtracking .

   jQuery Regularity and detail optimization

Have to mention jQuery Do a good job in detail optimization . There are many tips to learn , The next one will be jQuery Some of the programming techniques in , No more details here .

And then I want to talk about regular expressions ,jQuery A lot of regular expressions are used , I think if I study jQuery , Regular level will be greatly improved , If it's a regular white , I suggest to understand the following points before reading :

1) Understand and try to use Javascript Canonical correlation API, It includes test() 、replace() 、match() 、exec() Usage of ;

2) Distinguish the above 4 A way , Which is RegExp Object methods , Which is String Object methods ;

3) Understanding simple zero width assertions , Understand what matching is but not capturing and matching and capturing .

   jQuery Variable conflict handling

Finally, I would like to mention jQuery Conflict handling of variables , By saving the window.jQuery as well as windw.$ .

When conflicts need to be dealt with , Call static methods noConflict(), Give up control of variables , Source code is as follows :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
( function (window, undefined) {
     var
         // Map over jQuery in case of overwrite
         // Set alias , Mapped by two private variables window In the environment jQuery and $ Two objects , To prevent variables from being forcibly overwritten
         _jQuery = window.jQuery,
         _$ = window.$;
 
     jQuery.extend({
         // noConflict() Method to yield variables $ Of jQuery control power , So that other scripts can use it
         // Use full name instead of shorthand jQuery
         // deep -- Boolean value , Indicates whether thorough jQuery Variable reduction ( transfer $ Transfer at the same time of reference jQuery Object itself )
         noConflict:  function (deep) {
             // Judge the whole situation $ Is the variable equal to jQuery Variable
             // If it is equal to , Restore global variables $ by jQuery Variables before run ( Stored in internal variables _$ in )
             if  (window.$ === jQuery) {
                 // here jQuery Alias $ invalid
                 window.$ = _$;
             }
             // When deep conflict handling is turned on and global variables jQuery Equal to the inside jQuery, Take the overall situation. jQuery Revert to previous condition
             if  (deep && window.jQuery === jQuery) {
                 // If deep by true, here jQuery invalid
                 window.jQuery = _jQuery;
             }
 
             // What's back here is jQuery Internal library jQuery Constructors (new jQuery.fn.init())
             // Like use $ Just use it
             return  jQuery;
         }
     })
}(window)

Draw a simple flow chart to help understand :

So after giving up these two symbols , Whether it can't be used in our code jQuery Or $ Well ? Mo panic , Still usable :

1
2
3
4
5
6
7
8
9
// Give up jQuery 、$ Control of does not mean that it cannot be used jQuery and $ , The method is as follows :
var  query = jQuery.noConflict( true );
 
( function ($) {
 
// Plug in or other forms of code , You can also set the parameter to jQuery
})(query);
 
//  ... Other use $ Code of the library as an alias

jquery Source code interpretation of more related articles

  1. jQuery Source code interpretation three selectors

    Go straight up jQuery Source code interception code // Map over jQuery in case of overwrite _jQuery = window.jQuery, // Map over the $ i ...

  2. jQuery Source code interpretation --- The overall architecture

    I've been busy studying recently , Feel want to improve or read the source code , So prepare for the exam and start reading after the exam jquery Source code , come on. ~

  3. jQuery Source code interpretation ----part 2

    Separate constructors adopt new Operator to build an object , It usually takes four steps : A. Create a new object B. Assign the scope of the constructor to the new object ( therefore this It points to this new object ) C. Execute code in constructor D. Return to this new object And finally ...

  4. jQuery Source code interpretation - Event analysis

    The original event registration addEventListener The method should be familiar to everyone , It is Html The primitive way to register events with elements . Let's take a look at addEventListener Method signature : element.addEventList ...

  5. jQuery Source code interpretation - Data cache system :jQuery.data

    jQuery stay 1.2 After the introduction of jQuery.data( Data cache system ), The main function is to make a set of custom data available DOM The elements are related —— Simple to say : One to one association between an object and a set of data . A group and Element Relevant data ...

  6. jquery Source code interpretation ( Excerpt from jQuery Source code analysis series books (pdf)) Continuous updating

    1. Overall framework 1.1 Self calling anonymous functions // Self calling anonymous functions (function(window,undefined){ //jquery code})(window); 1. This is a self calling anonymous function . The first includes ...

  7. jQuery Source code interpretation one

    (function(window,undefined){...})(window); This is a typical self executing anonymous function . Why would there be one called undefined The formal parameters of ? undefined Is not a constant , Sure ...

  8. jQuery Source code interpretation ----part 1

    source : For class network https://www.imooc.com/video/4392 jQuery The overall architecture jQuery According to my understanding, it is divided into five parts , Selectors .DOM operation . event .AJAX With animation , So why is there 13 A model ...

  9. ( turn )jQuery Source code interpretation -- jQuery v1.10.2

    original text GitHub link : https://github.com/chokcoco/jQuery-

Random recommendation

  1. PDO Operating the database

  2. .net framework Version summary

    Version Release Date 1.0.3705.0 1RTM 2002/2/13 1.0.3705.209 1SP1 2002/3/19 1.0.3705.288 1SP2 2002/8/ ...

  3. oracle psql tuning

    1 not always sql The longer, the worse the performance , As much as possible where The condition makes the initial result set minimum , And then connect to other tables 2 Use patition 3 The same result set is used many times , have access to with table

  4. 2013 Multi-University Training Contest 10

    HDU-4698 Counting The question : Given a two-dimensional plane , among x The value is 1-N,y The value is 1-M, Now given K A little bit , Ask at least K One of the points satisfies the requirement <Xmin, Xmax, Ymin, Ymax& ...

  5. Or

    1.   Database table spaces and data files 2. About the analysis of the database port SQLSever  1433 MySql     3306 Oracle     1521 3. About listener.ora Location Modify the interface ...

  6. Read the file txt

    /// <summary>        /// Read the file         /// </summary>        /// <param name="path ...

  7. Linear storage structure -LinkedList

    LinkedList The internal structure is in the form of linked list , It's a two-way list . In addition to inheritance List Outside , And inherited Deque Interface , Can be used as a stack structure . private static final class Link<E ...

  8. Intent、Bundle—— Realization Activity Communication between

    http://blog.sina.com.cn/s/blog_62dea93001015847.html One application can have multiple Activity, But there is only one Activity As the entrance to the program , Others in the application ...

  9. HTML Common label attribute graph

  10. JS Timer settings 、 Cancel quickly

    1. First, define your own method function test() { alert(" Start "); } 2. Use in the timer setInterval("test()",1000 ...