Meet jQuery from evolving source code

Time:2019-12-2

What is the essence of jQuery?

A JavaScript library.
Accept an old node and return a new object (hash), which is the jQuery object.
The characteristic of jQuery is that it has its own API.
The source code of jQuery calls DOM API, but jQuery objects cannot use DOM API.

The convenience of jquery

JQuery greatly simplifies JS programming and is easy to learn.
Avoid using native DOM APIs that are “rotten and complex” as much as possible.
JQuery has excellent compatibility.
However, a lot of APIs and the timeliness of continuous updates are indispensable for a thorough understanding:
skill comes from practice.

The process of implementing jquery

It is the process of writing source code and repeatedly optimizing the implementation requirements.

First, let’s encapsulate the function

Here is just a function of “add class” as an example. In the actual development, we have to declare many functions to implement the method requirements.
We use simple HTML structure

<body>
    <div>111</div>
    <div>222</div>
    <div>333</div>
    <ul>
        <li id="item1">select1</li>
        <li id="item2">select2</li>
        <li id="item3">select3</li>
    </ul>
</body>

Functions:
Adds a class for the specified node.

Function addclass (node, classes) {// add one or more classes to the passed in element node
  classes.forEach((value)=>node.classList.add(value))
}

Addclass (Item3, ['a ','b']) // node with ID "Item3"

//<li id="item3" class="a b">select3</li>
Give them a namespace

Although the above functions have been preliminarily implemented, there is a big problem:
When we are dealing with complex pages, in order to facilitate use and memory, we may declare many functions whose names are very “similar” to DOM API; then we will unconsciously overwrite some functions inherent in API or global variables.

DOM API puts many methods in document object(window.document.xxx) We also need to give them a namespace, that is, write it to a library, to temporarily solve this problem. At the same time, it directly tells the developers:These functions we declare are inherently related, because they are all manipulating nodes.

Namespace:Namespace, also known as namespace, namespace, etc., represents the visible range of an identifier. An identifier can be defined in multiple namespaces, and its meaning in different namespaces is irrelevant. Namespace is a design pattern. (see Wikipedia for details)

For example, the author’s name =’sgs’

Window.sgs = {} // declare an empty library

Function addclass() {above}
sgs.addClass = addClass

sgs.addClass(item2,['a','c'])
//Achieve the same effect

In this way, we can call the methods of SGS library to achieve the same purpose, and avoid the coverage of global variables; at the same time, these methods are all in the same library we summarized.

After solving this problem, we found that we didn’t want to use an API like this.
Can we directly call a function to a nodeitem3.addClass()

How to achieve it? Put node in front
node.fn(x,y)

Let’s “tamper” with the prototype of node and add an attribute to the public attribute of node.
Replace all nodes in the function withthis, the default setting isthisPassed in as the first parameter.

Node.prototype.addClass = function(classes) { 
  classes.forEach((value)=>this.classList.add(value))
}

We can find the properties we added in node.prototype.
When using:

item3.addClass(['a','b','c'])
//=== item3.addClass.call(item3,['a','b','c'])

However, we are changing the public properties of node. So there’s a lot of trouble:
If many developers are changing public attributes, they will not only cover each other, but also lose the meaning of the most standard.

How to further improve?

We declare a similar “node” ourselves, named:“jQuery”

Window.jquery = function (node) {// incoming node
  return {
            //key: value
            
            node.APIOne: function(){}
            node.APITwo: function(){}
            ...
            node.addClass: function(classes){
               classes.forEach((value)=>node.classList.add(value))
            }
         }
}

This is how we use it now

Var node = jQuery (Item3) // first get a new object according to the node
Nodex. Addclass (['a ','b']) // use the new API provided by jQuery to operate

First, we pass the parameter Item3 to jQuery, and then jQuery stores it in the node of the function, so that when we use other methods, we can directly operate the node by operating the nodex object.

What if you passed in a string representing a CSS selector instead of a node?

When you pass in a selector representing a node instead of a node corresponding to an ID:

var nodex = jQuery('#item3')

Let jQuery source code judge the type of parameter passing:

window.jQuery = function(nodeOrSelector){
  let node
  if(typeof nodeOrSelector === 'string'){
    node = document.querySelector(nodeOrSelector)
    //If jQuery finds that you have entered a string, it will go back to find the node corresponding to the string
  }else{
    node = nodeOrSelector
  }
  return
  ...
}
If multiple element nodes are passed in

When you pass in a selector to select multiple element nodes

var nodex = jQuery('ul>li')
var nodey = jQuery('ul li:nth-child(2)')

Put all 1-N nodes in the pseudo array.

window.jQuery = function (nodeOrSelector) {
    //--------------------Judgment part--------------------
    let nodes = {}
    if (typeof nodeOrSelector === 'string') {
        Let temp = document.queryselectorall (nodeorselector) // pseudo array, but its prototype chain also covers many layers
        For (let I = 0; I < temp. Length; I + +) {// get the pure prototype chain, \
            nodes[i] = temp[i]
        }
        nodes.length = temp.length
    }Else if (nodeorselector instanceof node) {// indicates that a node is passed in, but consistency also needs to be changed into a pseudo array
        nodes = {
            0: nodeOrSelector,
            length: 1
        }
    }
    
    //--------------------Add class method--------------------
    nodes.addClass = function () { 
        Let array = [] // multiple string representative classes are passed in instead of arrays. Strings are internally combined into arrays
        for (let k = 0; k < arguments.length; k++){
            array.push(arguments[k])
        }
        array.forEach((value) => {
            For (let I = 0; I < nodes. Length; I + +) {// nodes is not an element, but a pseudo array
                nodes[i].classList.add(value)
            }
        })
    }
    
    //------------------Set node text method------------------
    Nodes. Settext = function (text) {// set the text of the incoming parameter
        for (let i = 0; i < nodes.length; i++) {
            nodes[i].textContent = text
        }
    }
    
    //-------------------------------------------------
    return nodes
}

//**We also introduce $, through which we declare jQuery objects:**

window.$ = jQuery

Use two APIs of jQuery:

var $div = $('div')
var $li = $('ul>li')
$div.addClass('active')
$li.setText('We are the same')

At this point, you can see that the essence of jQuery is a JavaScript library. Through an “evolutionary” process to achieve a standard of use. The API of jQuery is the function corresponding to the attribute in the source code, and the source code of jQuery is far more complex and cumbersome than this, so it can realize such a powerful function.

We can allow a principle to be used without a thorough understanding,Just like we introduced external libraries.

We are only here to visualize the basic principles of jQuery implementation. Only knowing the root and the bottom can we learn and use jQuery more thoroughly.

Edit By: Eden Sheng
EMail: [email protected]