JQuery source code framework analysis

Source: Internet
Author: User

Each framework has a core, and all the structures are based on this core. After the structure is established, the rest is the function stacking.

The core of jQuery is to match and operate elements from HTML documents.

Just like a building, let's get to know the cornerstone and structure of the building step by step.


1. Constructor

2. Chain syntax

3. Selector

4. scalability


1. Constructor

We know that class is an important concept of object-oriented programming. It is the highest abstraction of things, and it is a model. By instantiating a class, we can create an instance.

Javascript itself does not have the concept of classes. Only prototype is supported. What is prototype? It is an attribute set for the constructor. This attribute contains an object (prototype object ). This object contains the properties and methods shared by the instance object ). With such an attribute, we can share some things with all instances to implement the concept of class in object orientation.

The following is an example of the link --------------

Therefore, jQuery uses prototype inheritance to implement class

1 var jQuery = function () {} 2 3 jQuery. prototype = {4 // extended prototype object 5} 6 // Since the prototype name is too long, we can create another fn 7 jQuery. fn = jQuery. prototype = {8 // extended prototype object 9} 10/************************ I am a splitting line *** * *******************/11 // Similarly, jQuery can also be replaced by an alias $, therefore, the code can be written as 12 var $ = jQuery = function () {}; 13 jQuery. fn = jQuery. prototype = {14 // extended prototype object 15 jquery: "1.7.2", 16 size: function () {17 return this. length; 18} 19}

So how do we call it?

1 var my $ = new $ (); // instantiate 2 console. log (my $. jquery); // 1.7.23 console. log (my $. size (); // undefined

But jQuery does not call this method. It is similar to $ (). jquery.

That is to say, jQuery does not use the new instantiation, but directly calls the jQuery () function, followed by the jQuery prototype method. How can this problem be achieved?

 1 var $ = jQuery = function(){ 2     return  new jQuery(); 3 };     4 jQuery.fn = jQuery.prototype = { 5      6     jquery : "1.7.2", 7     size : function(){ 8         return this.length; 9     }10 }11 12 console.log($().jquery);13 console.log($().size());

If an error occurs according to the above method, the memory overflows, because the error is caused by cyclic reference during instance creation.

We need to return an instance. We know that this points to the new instance when a new object is created, and the instance obtains the prototype attribute method.

Therefore, we can create an instance using the factory method, place this method in the prototype object of jQuery. prototype, and then return the call of this prototype method in the jQuery function.

1 var $ = jQuery = function () {2 return jQuery. fn. init (); 3}; 4 jQuery. fn = jQuery. prototype = {5 init: function () {6 console. log (this); 7 return this; // return instance reference 8}, 9 jquery: "1.7.2", 10 size: function () {11 return this. length; 12} 13} 14 console. log ($ (). jquery); 15 console. log ($ (). size ());

In the console, this object is an instance of jQuery.

The init () method returns the this keyword, which references the jQuery instance. If you continue to use this keyword in init (), that is, the init function is considered as a constructor, how does this work?

var $ = jQuery = function(){    return  jQuery.fn.init();};    jQuery.fn = jQuery.prototype = {    init: function(){        this.length = 2;        this.test = function(){            return this.length;        }        return this;    },    jquery : "1.7.2",    length:0,    size : function(){        return this.length;    }}console.log($().jquery);console.log($().test()); //2 ? 0 ?console.log($().size()); //2 ? 0 ?

2 is returned. As you can see, this keyword references the object of the init function scope. When it accesses the length attribute, 2 is returned. This keyword can also access the scope of the jQuery. fn object of the upper-level object. Therefore, 1.7.2 is returned, and 2 instead of 0 is returned when the size method is called.

This design idea can easily undermine the independence of the scope, which may have a negative impact on the jQuery framework. Therefore, jQuery splits the scope by instantiating the init initialization type.

1 var $ = jQuery = function(){2     return new jQuery.fn.init();3 };    

In this way, we can isolate this in the init () constructor from the this keyword in the jQuery. fn object. Avoid confusion. However, this method causes another problem: the attributes and methods of jQuery. fn objects cannot be accessed.

Object [object Object] has no method 'SIZE '.

How can we split the scopes between the initialization constructor and the jQuery prototype object and access the jQuery prototype object in the return instance?

The jQuery framework cleverly solves this problem through prototype Transfer

1 jQuery. fn. init. prototype = jQuery. fn; // use the jQuery prototype object to overwrite the init prototype object.

In this way, new jQuery. fn. the new object created by init () has the prototype object method of the init constructor. By changing the prototype pointer to point it to the prototype of the jQuery class, in this way, the created object inherits jQuery. fn prototype object definition method.

Ii. scalability


Extend () functions used in jQuery custom extension methods

1 jQuery.extend = jQuery.fn.extend = function() {2     //code    3 }

Before talking about the source code, let's talk about copying, copying, and copying.

We know that js data types are different.

*Basic Type: Pass by value (undefined, NULL, boolean, String, Number)
*Reference Type: Pass the memory address Object


/* Deep copy: all elements and attributes are completely cloned and completely independent from the original referenced object. The cloned object has no relationship with the original object, that is, after you copy the object, any changes to the original object value will not affect the value of the cloned object */

Therefore, when performing a deep copy (clone) operation, we must copy every value in the object instead of the reference. In other words, we must use a recursive method to copy objects in a shortest.

1. Shallow copy

1 var clone = _. clone = function (obj) {2 // The returned value is not directly returned by the object. 3 if (typeof obj! = 'Object') return obj; 4 var result; 5 // The slice Method of the array does not change the original array 6 if (object. prototype. toString. call (obj) = "[Object Array]") {7 result = obj. slice (); 8} else {9 // object for Traversing 10 result ={}; 11 for (var name in obj) {12 result [name] = object [name]; 13} 14} 15 return result; 16}

2. Deep copy

1 var _ deepClone = function (source) {2 if (source = null) return null; 3 var result; 4 if (source instanceof Array) {5 result = []; 6 // if it is an array, call 7 for recursively (var I = 0; I
 
  

3. jQuery implementation

1 jQuery. extend = jQuery. fn. extend = function () {2 // it is best to write down all the variables used before the function definition. The reason is related to ECMA details 3 4 var options, name, src, copy, copyIsArray, clone, 5 target = arguments [0] | |{}, 6 I = 1, 7 length = arguments. length, 8 deep = false; 9 10 // determines whether it is a deep copy | shallow copy 11 if (typeof target = "boolean") {12 deep = target; 13 target = arguments [1] | |{}; // The returned target object 14 // skip deep during traversal | target parameter 15 I = 2; 16} 17 18 // for Example If the initial value is not an object and is not a function, it is null. For example, if a string "" is set to {}; 19 if (typeof target! = "Object "&&! JQuery. isFunction (target) {20 target ={}; 21} 22 23 // if you only have one parameter of your own, the parameter is not inherited by the clone, returns 24 if (length = I) {25 target = this; 26 -- I; 27} 28 29 for (; I <length; I ++) {30 // when the processing value is null undefined, 31 if (options = arguments [I])! = Null) {32 // The inherited object options33 34 for (name in options) {35 src = target [name]; // 36 copy = options [name] for the original object; // 37 38 For the object to be copied // prevents endless loops, if the original object is equal to the value (o) in the object to be copied ), // During o traversal, I assigned a value for re-traversal. 39 if (target = copy) {40 continue; 41} 42 43 // In the case of Array and Object, where deep is true and the input Object has a value (true, recursively call the method itself to perform a deep copy 44 if (deep & copy & (jQuery. isPlainObject (copy) | (copyIsArray = jQuery. isArray (copy)) {45 if (copyIsArray) {// if the object to be copied is an array 46 copyIsArray = false; 47 clone = src & jQuery. isArray (src )? Src: []; 48 49} else {50 clone = src & jQuery. isPlainObject (src )? Src: {}; 51} 52 53 target [name] = jQuery. extend (deep, clone, copy); 54 // if this is not the case, perform a shallow copy. We are executing jQuery. extend ({}) or jQuery. fn. extend ({}) is used to execute this method, but it does not understand why one is a custom extension of the JQuery class, and the other is a custom extension of the JQuery object, so what exactly is the target here? Let's look at the example 55} else if (copy! = Undefined) {56 target [name] = copy; 57} 58} 59} 60} 61 62 // return the modified target63 return target; 64 };

Note: AlthoughJQuery. extend = jQuery. fn. extend they are a method, but their specific functions are different, because this points to different.

Function jQuery () {}// create a prototype Object using the literal method. Here {} is the Object, which is an Object. The new Object is equivalent to {} jQuery. fn = jQuery. prototype = {constructor: jQuery, // force pointing to jQueryname: 'Lee ', age: 100, run: function () {return this. name + this. age + 'running... ';}}; jQuery. extend = jQuery. fn. extend = function () {var option = arguments [0]; for (var v in option) {this [v] = option [v] ;}return this ;}; var jquery = new jQuery (); document. write ("

"+ JQuery. extend ({add: function () {alert (" aaaa ") ;}}) +"

"); Document. write ("

"+ JQuery. fn. extend ({minu: function () {alert (" bbbb ") ;}}) +"

"); JQuery. add (); jquery. minu ();
This prints the result

Function jQuery (){}

[Object Object]


In the constructor module, we can see that

This of jQuery. extend is the jQuery class, which is added to the jQuery class (object, method)

This of jQuery. fn. extend is the prototype of jQuery. Add (object, method) on the jQuery prototype. What methods will JQuery object have?

JQuery. fn = jQuery. prototype

4. A simplified version

1 var _ deepClone = function (source) {2 if (source = null) return null; 3 var result; 4 if (source instanceof Array) {5 result = []; 6 // if it is an array, call 7 for recursively (var I = 0; I
   
    

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.