Question and answer form read jquery source (ii)

Source: Internet
Author: User
Tags naming convention

The author of this article is mainly designed to explore the source code of jquery, many people say that jquery design is too individualistic, in fact, this is a certain bias, because good design is universal, common, jquery so easy to use, how can we say that his design is individualistic? Okay, get to the chase.

Question: How does jquery expose its API?

Any framework is actually a façade mode, the external and frame communication must pass through a unified façade, and this façade is what we say the API. So to learn the source code of any framework, we have to understand two things:

1. Which is a private method, because the private method is used internally by the framework itself, which he does not want to expose to peripheral users, and these methods are not available as APIs, even if users can see them.

2. Which methods are APIs, they are really exposed to the user's use. The definitions of these methods tend to be interface-oriented, relatively stable, and do not change because of internal changes in the framework. Only in this way, the user of the framework will not modify their own code because of the upgrade framework, which conforms to the "open and closed principle".

So how does jquery implement façade mode and expose its own API?

A: jquery is created on the window, and only two objects are created on window, one is "$", one is "jQuery", and the two are the same object.

Window.jquery = window.$ = JQuery;

Why does jquery expose two objects of the same kind? The main thing is that jquery is six characters, it is more troublesome to play, so it is replaced by the alias "$" of a character, so that the user can play five characters less-_-| | Many frameworks also expose two of objects, such as underscore, Lodash.

jquery (hereinafter referred to as $) itself is a function, by calling this function we can return an object, we call the jquery object, the JQuery object prototype is JQuery.fn.init, in this prototype jquery provides a lot of methods for the use of the user. $ Although it is a function, but the function can also have its member variables, so the $ own member variable we can also be used.

So jquery offers three APIs:

One is jquery itself, which is a function and an API that can create jquery objects.

The api,jquery on another jquery object provides the user with a list of member methods on the JQuery object, in the form of an extended prototype.

Finally, the member methods above the $ function, which can also be used as global methods and Util methods.

And jquery does not indicate the private (because JS itself syntax limitations, so many private members can be seen externally, for such a private member, we will create a naming convention to differentiate, such as "$", "_", "$$" beginning, etc.), all exposed methods are API.

Question: How is jquery created on window?

A: The main building pattern of jquery is to extend itself with a iife, which is the benefit of not polluting the global scope. At the same time using strict mode "use strict", strict mode declaration must be placed in the Iife, the same is to not pollute the overall, after all, you can not let your users must use strict mode.

jquery is being constructed by passing parameters in the form of parameters that are passed in as Iife blocks.

At the same time jquery recognition commonjs,jquery will identify exports, you can directly require (' jquery.js ') to the introduction of jquery. It is important to note that if the global scope supports the Document object in a COMMONJS environment, it is created at the global scope, and if it is not supported, a new factory function is returned, and the user, when needed, goes through the new constructor to create jquery, It is also necessary to pass the document into.

//using Iife, the entire process of jquery creation is encapsulated in a closure and then the global variable (if the browser environment is window, if the COMMONJS environment is the current scope) and the factory function is passed in(function(Global, factory) {//Strict mode in closures also does not pollute the global scope"Use Strict"; //This is to determine whether it is a commonjs environment, if it is to use COMMONJS to the results of the construction of jquery output. If not, build jquery with global variables    if(typeofmodule = = = "Object" &&typeofModule.exports = = = "Object") {Module.exports= Global.document?Factory (Global,true ) :            function(w) {if( !w.document) {Throw NewError ("jQuery requires a window with a document" ); }                returnFactory (W);    }; } Else{Factory (global); }//based on whether the browser environment is determined by the window})(typeofWindow!== "undefined"? window: This,function(window, noglobal) {//the ongoing build process    varJQuery =function(Selector, context) {return NewJQuery.fn.init (selector, context); }        //if the COMMONJS output does not build jquery on the window, it is output directly with the return value    if( !Noglobal) {Window.jquery= window.$ =JQuery; }    returnjQuery;}); 
Question: Does jquery support run on Nodejs?

Since jquery supports COMMONJS, can he run it in node?

A: We run on NPM

NPM Install JQuery

It can be installed, but let's look at his code and find out that it's not a thing we're reading now. We read the version of the jquery Package.json inside, the entry file is Dist/jquery.js, and we install the entry function on node instead of this. We went to NPM's jquery package homepage and found that his git address is not the address we are reading now, and that the version is inconsistent with ours, which means that the jquery above is not the project we are reading now.

Since the jquery in NPM and the jquery we are reading now are not a project, I have not explored it further. jquery relies entirely on the browser model, and if node does not have a model that cannot run, it is a bit of a fuss to run jquery to emulate such a model. I previously used another API in node-side imitation jquery Project--cheerio,cheerio very much like jquery, a friend familiar with jquery can get started quickly, we can use this to handle DOM operations in node, This is ideal for grabbing data such as packet extraction.

In short, jquery is designed for the browser, in the non-browser environment, try not to consider the use, because there must be better alternatives.

Question: The $ function is exactly what it implements?

A: Allen treats the $ function as an anti-pattern design, because $ is the only entry for jquery and forces several different functions to be overloaded to a single function. This benefit is obvious, simplifying the external API, making the entire jquery API more concise, learning more simple and fast. The entire framework of jquery is designed to be fast and concise, which is in line with his own design needs.

However, this design is anti-pattern, mainly with the "single principle of responsibility" conflict, forcing several completely different functions of overloading together, is not conducive to the user's understanding of it. An overloaded function is a policy with the same name as a function of several functions with different parameters. Because these functions are functionally identical, the same name is better for everyone to learn and maintain. The function overloading of different functions is undesirable, which is not in accordance with the design pattern.

However, the appropriate anti-pattern, in exchange for the simplicity and use of the API, which is conducive to user learning and use.

Specific as follows:

First the $ function is new with a $.fn.init object:

var function (Selector, context) {    returnnew  jQuery.fn.init (selector, context);}

What exactly did this jQuery.fn.init method do? The author summarizes a total of 4 functions:

1. Select the DOM from the jquery selector and encapsulate it as a jquery object to return

2. Generate the DOM fragment from the HTML fragment and encapsulate it as a jquery object to return

3. Encapsulation and implementation of domcontentloaded events

4. Encapsulate any object as a jquery object

Question: How does jquery extend to itself?

A: The core function of jquery is $.extend, which implements a object.assign function like ES6, whose ultimate goal is to implement mixin design patterns.

Mixin mode, also known as weaving mode. is to provide classes that can be simply inherited by one or a group of subclasses, with the intention of reusing their functionality. Unlike the traditional idea of inheriting, mixin is implemented by means of an extended object, and the benefit is that you can create the object before extending it. This design pattern is one of the most important design patterns in JavaScript, and he takes full advantage of JavaScript's ability to dynamically extend the object, enabling prototype mode, inheritance, and so on.

The core purpose of the $.extend function is to implement the Mixin mode, of course, $.extend function is not only so, but also can be cloned object, deep copy, replace Object.assign and other functions. However, for self-extension is the function of the core function, we would like to look at the creation of jquery object process.

jquery itself is a function that, after its creation, creates a basic prototype FN for itself.

Jquery.fn = Jquery.prototype = {    //  very few methods     ...}

The Extend function is then defined on its own and on its own prototype.

function () {     ...      }

It then uses extend to extend its own functionality on its prototype.

Jquery.extend ({    ...}) JQuery.fn.extend ({    ...})

The whole process of creating jquery is to use the mixin pattern to extend functionality to itself. At the same time, since the extension of the mixin mode is done after the object is created, we do not have to worry about extending the function to modify the previous code, more to reflect the "open and close principle."

At the same time, the ability to extend jquery with extend is officially recommended, and jquery's own code is used in this way, so we should try not to use "$.fn.xxx =" When we extend jquery, but instead use jquery to expose api--to us " $.fn.extends (...) ", this is the most standard usage, try not to use the" $.fn.xxx = ... "form. Only in this way will our code worry about compatibility issues with the future because of the jquery version upgrade.

Question: What is jquery's intention to rename its prototype to "FN"?
Jquery.fn = Jquery.prototype = {    ...}

As can be seen from the above code, jquery's FN is the JavaScript syntax prototype prototype, why should this be designed?

A: Simple and said, or for brevity, conducive to compression, because FN than prototype less than 7 characters-_-, but I think there is a deeper meaning.

Or go back to the façade mode, prototype is the JavaScript grammar level, belongs to jquery's private, and jquery also wants to expose its own prototype, so it needs to be encapsulated, even if the package is just a name change. We can imagine that if the future jquery modifies its own API structure and no longer directly uses the prototype-JS-provided prototype, the API that he provides externally can be unmodified because he exposes FN instead of prototype. Of course, the possibility of this modification is negligible, but the author of jquery took it into account, reflecting the author's solid basic skills, a deep understanding of design patterns and design principles, which we should learn.

This is why JavaScript exists prototype this syntax, but jquery is not used directly, but instead renamed to FN. So when we write the prototype extension of jquery, we try to use "$.fn.extends ({...}"). Instead of using "$.prototype.extends ({...})" extended to it.

Question: How does jquery new The jquery object?

It seems that a lot of people here don't understand the comments of Alan's blog. In particular, its prototype and the handling of this is not understood.

A: We have analyzed several functions of the jquery $ function, most of which are encapsulating jquery objects. In fact, the $ function itself is a factory function, and the jquery object is created by means of the factory function encapsulation method. The process is subtle, as we have said before, that the real jquery object is JQuery.fn.inti.

function (Selector, context, root) {...}
Init. jQuery. fn;

From the code above, I can see that the prototype of Init equals the prototype of jquery.

Why did you do it? jquery uses $ () instead of new $ (), so that a 4-character-_-is lost, and it also conforms to the factory model, after all, the direct use of syntax-level new is not in accordance with Factory mode. At the same time, the prototype of jquery was assigned to the prototype of JQuery.fn.init. The purpose of this design is not just to save a few characters, More importantly, JQuery.fn.init's prototype is also part of the jquery API, in fact, the prototype of jquery itself is not our API, because the jquery object's prototype is a JQuery.fn.init object, not jquery. However, the use of jquery as a prototype API is more conducive to user understanding and usage.

So there will be:

JQuery.fn.init.prototype = Jquery.fn;

The meaning of this code is to use JQUERY.FN instead of JQuery.fn.init.prototype as a prototype of jquery's externally exposed jquery object. So our expansion of the JQUERY.FN will naturally extend to jQuery.fn.init, because JQuery.fn.init's prototype is Jquery.fn, and the jquery object is a JQuery.fn.init object, so it will naturally extend to the jquery object as well.

So why would jquery create a jQuery.fn.init to be used as a prototype of a JQuery object, rather than just a new self in the jquery function?

This point Allen's blog has given an explanation, directly in the construction method inside the new method to create itself, will fall into a dead loop. The beauty of the jquery design is that it defines jQuery.fn.init as the prototype of the JQuery object, and this is transparent to the user, without needing to know his presence or knowing the existence of JQuery.fn.init.prototype. This exposes the API is the most concise API, for the benefit of everyone.

You can refer to Alan's blog, the process is very detailed, this is no longer described here. Allen's blog is more grammatical, and the author is more from a design point of view, jquery is doing so, its purpose is to pursue the most concise API for external exposure. So the interior of jquery is designed to be so complex and subtle.

Question: How does the jquery object implement the collection process?

A: I have always thought that jquery object essence is a way to inherit the array object through the prototype obtained. But we go back to the previous section of the code, we will be a few pieces of code to tidy up, you can get

JQuery.fn.init.prototype = Jquery.fn = Jquery.prototype = {...};

You can see that the jquery object is an ordinary object and should not be said to be "Array-like object". Because jquery itself has length, it is actually a patterned array that defines an ordinary object with an index and length. We can say that this object is "Array-like object".

Jquery.fn = Jquery.prototype = {    ...     0,}

Because length=0 is defined as a prototype of jquery, it is equivalent to an empty "Array-like Object".

We can look at the JQuery.fn.init construction method.

init = JQuery.fn.init =function(selector, context, root) {if( !selector) {        return  This; }    ...    if(typeofselector = = = "string" ) {        if(...) {Jquery.merge ( This, jquery.parsehtml (match[1], Context&& Context.nodetype? context.ownerdocument | |Context:document,true            ) ); return  This; } Else if(...) {Elem= document.getElementById (match[2 ] ); if(elem) { This[0] =Elem;  This. length = 1; }            return  This; }        ...    } Else if (...) {         This[0] =selector;  This. length = 1; return  This; } Else if (...) {        return ...    } Else...    returnJquery.makearray (Selector, This );};

The method calls the Jquery.makearray function, the Jquery.merge function, or "[]" and "length" to the this extension before the return, which is the handler function for the Arraylike object. Because this is the object that owns the Jquery.fn prototype, this here is a Arraylike object, and after Jquery.makearray, Jquery.merge and so on are still a Arraylike object, so the final return is a Arraylike object.

In addition, jquery provides a function that determines whether an object is arraylikeobject. If the object is a Arraylike object, jquery also provides many related functions for working with set operations, such as get, filter, each, merge, and so on. These functions are all array functions, but arraylike objects are actually applicable, in fact, many array methods, can be used for Arraylike objects, interested can check the "Array-like object" related articles.

Question: How does jquery implement chained operations?

Answer: Very simple answer, is "return this". For collection operations, you can use Jquery.each.

The Jquery.each design is very ingenious, because he himself will return himself:

jquery.extends ({each    :function(obj, callback        ) {... return obj;            }}) ; JQuery.fn.extends ({    function(callback) {        return this , callback);    },});

With each, we can easily wrap a number of set operations into a form that supports chained operations.

Togglefunction(state) {if(typeofstate = = = "Boolean" ) {        returnState? This. Show (): This. Hide (); }    return  This. each (function() {        if(Ishidden ( This) {jQuery ( This). Show (); } Else{jQuery ( This). Hide (); }    } );}

Using this form, a set operation function can be easily packaged to support chained operations.

We write jquery plugins, and many times we need to support jquery's link operations, and using each to encapsulate our own plugins is a good choice.

At the same time, the set operation function of jquery, also supports the chain operation, the set operation of jquery, will cache the previous collection, we can get the collection before the set operation through the Prevobject and end method, such operations greatly increase the application of the column chain operation.

Other APIs that support chained operations have $. Deferred, jquery animation operation, etc., here is not open.

Question: How does jquery do version control?

A: We know that jquery is going to take two variable names to window, "$" and "jquery", $ is an alias, and jquery is the real name, so when jquery is created, it saves the original "$" and "jQuery" variables on the window. And then you create yourself.

It also provides the functionality that will save the "$" and "jQuery" variables in the original noconflict:

_jquery = Window.jquery, _$ =function(deep) {    if (window.$ = = = JQ uery) {        = _$;    }     if (Deep && Window.jquery = = = JQuery        ) {= _jquery;    } return jQuery;};

Many libraries do so in version control, such as underscore.

For more information about the version, refer to the author's previous blog jquery version compatibility experiment.

Question and answer form read jquery source (ii)

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.