JQuery 2.0.3 Source Analysis Core (a) overall architecture _jquery

Source: Internet
Author: User
Tags object object shallow copy

Read an open source framework, the most want to learn is the design of ideas and implementation techniques.

Needless to say, the analysis of jquery has been rotten for so many years and has been read long ago,

But these years have been to do mobile end, has been the Queen Zepto, recently took some time to give jquery again to sweep again

I will not be scripted translation of the source code, combined with their actual experience to read it together!

GitHub on the latest is Jquery-master, joined the AMD specification, I will take the official latest 2.0.3 as the subject

Overall architecture

The core of the jquery framework is to match elements from HTML documents and perform actions on them,

For example:

Copy Code code as follows:

$ (). Find (). CSS ()
$ (). Hide (). html (' ... '). Hide ().

There are at least 2 problems that can be found in the above wording.

1. How jquery objects are built

2. How the jquery method is invoked

Analysis One: jquery's no new build

JavaScript is a functional language, a function can implement classes, and classes are the most basic concepts in object-oriented programming.

Copy Code code as follows:

var aquery = function (selector, context) {
Constructors
}
Aquery.prototype = {
Prototype
Name:function () {},
Age:function () {}
}

var a = new Aquery ();

A.name ();

It's a routine use, and it's obvious that jquery doesn't play that way.

jquery does not use the new runtime to instantiate the jquery display or call its function directly

In the way jquery writes,

Copy Code code as follows:

$ (). Ready ()
$ (). Noconflict ()

To do so, jquery is supposed to be a class, then $ () should be an instance of the returned class

So change the code:

Copy Code code as follows:

var aquery = function (selector, context) {
return new Aquery ();
}
Aquery.prototype = {
Name:function () {},
Age:function () {}
}

Through the new Aquery (), although the return is an instance, but also can see the obvious problem, the dead loop!

So how do you return to a correct instance?

Instance this is only related to prototypes in JavaScript

Then you can create an instance of the jquery class as a factory method and put it into the Jquery.prototye prototype.

Copy Code code as follows:

var aquery = function (selector, context) {
return AQuery.prototype.init ();
}
Aquery.prototype = {
Init:function () {
return this;
}
Name:function () {},
Age:function () {}
}

When executing the instance returned by Aquery ():

Obviously Aquery () returns an instance of the Aquery class, so this in Init is actually an instance of the Aquery class that points to

Here's the problem. Init's This is pointing to the Aquery class, and if the init function is also treated as a constructor, then what about the internal this?

Copy Code code as follows:

var aquery = function (selector, context) {
return AQuery.prototype.init ();
}
Aquery.prototype = {
Init:function () {
This.age = 18
return this;
},
Name:function () {},
Age:20
}

Aquery (). Age//18

This is an error, because this only points to the Aquery class, so you need to design a separate scope.

The processing of the jquery framework separator scope

Copy Code code as follows:

JQuery = function (selector, context) {
The JQuery object is actually just the Init constructor ' enhanced '
Return to New JQuery.fn.init (selector, context, rootjquery);
},

It is clear that by using the instance init function, a new Init instance object is built each time to separate this to avoid interaction confusion

Well, since it's not the same object, then there's definitely a new problem.

For example:

Copy Code code as follows:

var aquery = function (selector, context) {
return new AQuery.prototype.init ();
}
Aquery.prototype = {
Init:function () {
This.age = 18
return this;
},
Name:function () {},
Age:20
}

Uncaught Typeerror:object [Object Object] has no method ' name '
Console.log (Aquery (). Name ())

Throws an error and cannot find this method, so it is obvious that new Init is separated from the jquery class this

How do I access the properties and methods on the jquery class prototype?

Is it possible to isolate scopes and use the scope of the jquery prototype object, and to access jquery's prototype objects in the return instance?

Key points to achieve

Copy Code code as follows:

Give the INIT function the JQuery prototype for later instantiation
JQuery.fn.init.prototype = Jquery.fn;

Solve the problem through prototype delivery, and pass the jquery prototype to JQuery.prototype.init.prototype

In other words, jquery's prototype object covers the prototype object of the Init Builder

Because it's a reference pass, there's no need to worry about the performance of this circular reference.

Copy Code code as follows:

var aquery = function (selector, context) {
return new AQuery.prototype.init ();
}
Aquery.prototype = {
Init:function () {
return this;
},
Name:function () {
Return This.age
},
Age:20
}
AQuery.prototype.init.prototype = Aquery.prototype;
Console.log (Aquery (). Name ())//20

Baidu borrow a map of netizens to facilitate direct understanding:

FN explained that in fact this FN does not have any special meaning, just jquery.prototype reference

Analysis Two: Chained call

Processing of DOM chained calls:

1. Save JS Code.

2. The return of the same object, you can improve the efficiency of the Code

Cross-browser chained calls are implemented by simply extending the prototype method and by return to this form.

Use the simple factory model under JS to specify the same instance of all operations for the same DOM object.

That's a very simple principle.

Copy Code code as follows:

Aquery (). Init (). Name ()
Decomposition
A = Aquery ();
A.init ()
A.name ()

To break down the code, it is clear that the basic condition of the chain is that the instance this exists and is the same

Copy Code code as follows:

Aquery.prototype = {
Init:function () {
return this;
},
Name:function () {
return this
}
}

So we're going to need a chained approach to access this, because we can return this to the current instance and then access our own prototypes.

Copy Code code as follows:

Aquery.init (). Name ()

Advantages: Save code, improve code efficiency, code looks more elegant

The worst thing is that all object methods return the object itself, which means there is no return value, which is not necessarily appropriate in any environment.

JavaScript is a non-blocking language, so he is not blocking, but not blocking, so he needs to drive through events, asynchronous to do some of the operations that need to block the process, so that processing is only synchronous chain, asynchronous chain jquery since 1.5 introduced promise, Jquery.deferred later in the discussion.

Analysis of three: plug-in interface

The main framework of jquery is this, but according to the custom of the General designer, if you want to add a property method to jquery or jquery prototype, if you want to provide the developer with an extension of the method, it is appropriate to provide an interface from the encapsulation point of view. The literal understanding is to extend the function, not to look directly at modifying the prototype. Friendly user interface,

JQuery supports its own extended attributes, which provide an interface, JQuery.fn.extend () to add methods to objects

As you can see from the jQuery source, Jquery.extend and jQuery.fn.extend are actually different references to the same method

Copy Code code as follows:

Jquery.extend = JQuery.fn.extend = function () {

Jquery.extend extends the properties and methods of jquery itself

JQuery.fn.extend extends the properties and methods of Jquery.fn

The Extend () function makes it easy to quickly extend functionality without disrupting the jquery prototype structure

Jquery.extend = JQuery.fn.extend = function () {...}; This is even, that is, 2 points to the same function, how can achieve different functions? This is the power!

For FN and jquery are actually 2 different objects that were previously told:

When Jquery.extend calls, this refers to the jquery object (jquery is a function and Object!). ), so it expands on jquery.
When JQuery.fn.extend calls, this points to the FN object, Jquery.fn and Jquery.prototype point to the same object, and extension FN is the extension Jquery.prototype prototype object.
This adds to the prototype method, which is the object method. So the jquery API provides the extension functions in the 2 above.

The realization of Extend

Copy Code code as follows:

Jquery.extend = JQuery.fn.extend = function () {
var src, copyisarray, copy, name, options, clone,
target = Arguments[0] | | {},//Common usage jquery.extend (obj1, Obj2), at this point, Target is arguments[0]
i = 1,
Length = Arguments.length,
Deep = false;

Handle a deep copy situation
if (typeof target = = "Boolean") {//If the first argument is true, that is, Jquery.extend (true, obj1, obj2);
Deep = target; Target is true at this time
target = Arguments[1] | |    {}; Target changed to Obj1
Skip the Boolean and the target
i = 2;
}

Handle case as Target is a string or something (possible in deep copy)
if (typeof target!== "Object" &&!jquery.isfunction (target)) {//Handle strange situations, such as jquery.extend (' Hello ', {nick: ') Casper}) ~ ~
target = {};
}

   //Extend JQuery itself if only one argument is passed
    if (length = = i) {&N bsp; //Handle this situation jquery.extend (obj), or jQuery.fn.extend (obj)
        target = this; //Jquery.extend When this refers to Jquery;jquery.fn.extend, this refers to Jquery.fn
         I.;
   }

    for (; i < length; i++) {
       //only deal with Non-n ull/undefined Values
        if (options = arguments[i])!= null) {//For example Jquer Y.extend (Obj1, Obj2, Obj3, OJB4), options for Obj2, obj3 ...
           //Extend The base object
             for (name in options) {
                 src = target[name];
                copy = options[ Name];

Prevent never-ending Loop
if (target = = copy) {//Prevent self reference, do not repeat
Continue
}

recurse if we ' re merging plain objects or arrays
If it is a deep copy, and the copied property value itself is an object
if (deep && copy && jquery.isplainobject (copy) | | (Copyisarray = Jquery.isarray (copy)) ) {
if (Copyisarray) {//copied attribute value is a number of groups
Copyisarray = false;
clone = src && jquery.isarray (src)? SRC: [];

else {The copied attribute value is a plainobject, such as {nick: ' Casper '}
clone = src && jquery.isplainobject (src)? src: {};
}

Never move original objects, clone them
target[name] = Jquery.extend (deep, clone, copy); Recursion ~

Don ' t bring in undefined values
else if (copy!== undefined) {//Shallow copy with property value not undefined
target[name] = copy;
}
}
}
}

Return the Modified Object
return target;

Summarize:

    constructs a new object via new JQuery.fn.init (), with methods for prototype prototype objects of the Init constructor
    By changing the direction of the Prorotype pointer, the new object also points to the prototype of the JQuery class prototype
    so the objects that are built continue to jquery.fn all the methods defined by the prototype

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.