A brief discussion on jQuery core architecture design
jQuery is no stranger to everyone, so I won’t say much here about what it is and what it does. The purpose of this article is to discuss the core of jQuery through a simple analysis of the source code. Architectural design, and how jQuery leverages advanced features in JavaScript to build such a great JavaScript library.
1 First introduction to jQuery
From the core function point of view, jQuery only does one simple and ordinary thing: query. Its syntax is so concise and clear that many people have already used jQuery without knowing what javascript is. To describe it in one word, it is: simplicity and simplicity. From a design perspective, we can divide the methods provided by jQuery into two major categories: static methods and instance methods. Static methods are methods accessed directly through $. These methods generally do not operate on DOM elements, but provide some common tools, such as ajax requests and some common operations on strings. In addition, jQuery also provides With its own extension mechanism, you can write the components you need through the extend method. The instance method is different from the static method. It is used to operate on the DOM elements queried by jQuery. jQuery executes $() to construct a jQuery object. This object stores all the DOM elements queried in an array method, and then in this The object's prototype chain implements methods for operating these DOMs. For example, the each() method is used to traverse each DOM element. You may notice that I just said that this object is stored "as an array", that is to say, the object constructed by jQuery is not an array, so what exactly is this object? In fact, this object is the core of jQuery, also known as "jQuery object". Therefore, the focus of this article is to analyze and discuss jQuery objects.
2 jQuery object
Generally, we will use jQuery like this:
$('div').each(function(index){ //this ...});
$('div') After execution, a jQuery object is returned. The each() method traverses the DOM elements in this object. Let's first look at the execution process of $('div') (the source code of this article is taken from jQuery 3.0):
jQuery = function( selector, context ) { return new jQuery.fn.init( selector, context ); }
This method is the entry method of $('div'). $ is the abbreviation of jQuery, which is equivalent to jQuery('div'). It can be seen that this method only does one thing. That is to return the instance object of the jQuery.fn.init() function. So what is jQuery.fn.init? Let’s look at the following code:
init = jQuery.fn.init = = jQuery.fn;
jQuery.fn. init and init refer to the same method. This method queries the qualified DOM elements based on the selector and returns them. But you will find that what is returned is this. What is this? We will analyze it later. Let’s first look at the following sentence:
init.prototype = jQuery.fn;
What does this sentence mean? This sentence makes the prototype object of the init method point to the jQuery.fn object. , so what the hell is jQuery.fn? Let's continue to look at the code:
jQuery.fn = jQuery.prototype = { // The current version of jQuery being used jquery: version, constructor: jQuery, // The default length of a jQuery object is 0 length: 0, // Execute a callback for every element in the matched set. each: function( callback ) { return jQuery.each( this, callback ); }, splice: arr.splice };
In order to save space, I have omitted some of the code. As can be seen from here, jQuery.fn is actually the prototype object of jQuery. This prototype object is defined in There are some methods to operate on this object. If you feel a little confused at this point, don't worry, let's sort out the ideas: jQuery first defines an init method, and then defines a series of operation methods on the init prototype object prototype. Finally, the instance object of the init method is returned. So the above process can be simplified as follows (pseudocode representation):
var init = function(selector,context,root){ //... return this; } init.prototype = { length:0, each:function(callback){ //... }, splice:[].splice } jQuery = function(selector,context,root){ return new init(selector,context,root); }
Then the question is, why are the methods in jQuery.fn not directly defined on the init prototype, but defined On jQuery's prototype object?
Actually, the purpose of this is to improve the query efficiency of jQuery. If it is directly defined on the prototype object of init, then every time a query is executed, such a huge prototype object will be created in the memory, and If this object is defined on jQuery's prototype, this object will be initialized when jQuery is loaded and will always exist in memory. Every time $() is executed in the future, you only need to point the prototype in init to this object. Instead of creating the same object every time.
Let’s take a look at what exactly this is returned in the init function. I said in my previous blog that this in the function always points to the caller during runtime. So who is the caller of init? ? It seems that the caller cannot be found in the above code. At this time, we need to deeply understand the operating mechanism of the new operator. Borrowing from my previous description of the new operator in my blog, we will carry out the execution process of new init(). It’s broken down as follows:
new init(selector,context,root) = { var obj = {}; obj.__proto__ = init.prototype; init.call(obj,selector,context,root); return typeof result === 'obj'? result : obj; }
It can be seen from the above decomposition process that when JavaScript creates an instance object through new, it will first create a common object obj, and then point the internal attribute __proto__ of obj to the prototype object of init, so obj The prototype chain will be changed, and step 3 uses the call method to call init(), so this in init refers to the obj object here.
After init() is executed, will store all matched DOM objects in the form of an array into this object and return it, that is, the obj object will be returned, and the new operator will eventually This obj object is returned as the new instance object. So the instance object returned by the new operator has two characteristics: first, it contains the DOM query result set, and second, its prototype chain inherits the prototype of init, and the prototype of init points to the jQuery.fn object, so Instance objects also have these operation methods.
jQuery creates a jQuery object every time a query is executed, and in the same application, all jQuery objects share the same jQuery prototype object. Therefore, the jQuery object not only contains the DOM query result set, but also inherits the operation methods on the jQuery prototype object. In this way, you can directly call methods to manipulate these DOM elements after querying. This is the core architecture design of jQuery, which is simple, convenient and practical!
If you still don’t understand the above explanation, don’t worry, I wrote a complete small project jDate according to jQuery’s design ideas, you can compare and understand! The jDate project has been uploaded to GitHub. You can click here to view the complete code: jDate. If you have different opinions, please feel free to discuss!
3 Defects of jQuery
By analyzing the core architecture of jQuery, we will find that every time a query is executed, jQuery will build a complex jQuery in memory Object, although every jQuery object shares the same jQuery prototype, the query process of jQuery is far more complicated than you think. It must consider various matching identifiers and the compatibility of different browsers. Therefore, if you only do some simple operations on the DOM, it is recommended to use the native method querySelector instead of jQuery. However, when using the native method, you may have to do some compatibility work for different application scenarios. You must learn to make trade-offs and not overdo it. Depends on jQuery!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



GolangRabbitMQ: The architectural design and implementation of a highly available message queue system requires specific code examples. Introduction: With the continuous development of Internet technology and its wide application, message queues have become an indispensable part of modern software systems. As a tool to implement decoupling, asynchronous communication, fault-tolerant processing and other functions, message queue provides high availability and scalability support for distributed systems. As an efficient and concise programming language, Golang is widely used to build high-concurrency and high-performance systems.

With the rapid development of the Internet of Things and cloud computing, edge computing has gradually become a new hot area. Edge computing refers to the transfer of data processing and computing capabilities from traditional cloud computing centers to edge nodes of physical devices to improve data processing efficiency and reduce latency. As a powerful NoSQL database, MongoDB is attracting more and more attention for its application in the field of edge computing. 1. Practice of combining MongoDB with edge computing In edge computing, devices usually have limited computing and storage resources. And MongoDB

With the rapid development of the Internet, software development has become more and more complex. In order to meet this challenge, software architecture has also continued to evolve, from the initial single application to a microservice architecture. With the popularity of microservice architecture, more and more developers are beginning to adopt gRPC as the communication protocol between microservices. go-zero is a microservices framework based on gRPC. This article will introduce go-zero’s architectural design patterns and best practices. 1. go-zero framework architecture Figure 1: go-zero framework architecture Figure 1

As a high-performance programming language, Go language is very popular in the construction of distributed systems. Its high speed and extremely low latency make it easier for developers to implement highly scalable distributed architectures. There are a lot of architectural issues to consider before building a distributed system. How to design an architecture that is easier to maintain, scalable and stable is an important issue faced by all distributed system developers. Using the Go language to build distributed systems can make these architectural choices simpler and clearer. Efficient coroutines The Go language natively supports coroutines.

Architectural design and PHP code implementation of the mall SKU management module 1. Introduction With the rapid development of e-commerce, the scale and complexity of the mall are also increasing. The SKU (StockKeepingUnit) management module of the mall is one of the core modules of the mall and is responsible for managing the inventory, price, attributes and other information of the products. This article will introduce the architectural design and PHP code implementation of the mall SKU management module. 2. Architecture design Database design The database design of the SKU management module is the foundation of the entire architecture. SKU of the mall

Large-scale PHP projects can adopt framework-based architectural design, such as layered architecture or MVC architecture, to achieve scalability, maintainability and testability. The layered architecture includes the view layer, business logic layer and data access layer; the MVC architecture divides the application into models, views and controllers. The implementation framework architecture provides a modular design that makes it easy to add new features, reduce maintenance costs, and supports unit testing.

How to design a high-performance PHP microservice architecture. With the rapid development of the Internet, microservice architecture has become the first choice for many enterprises to build high-performance applications. As a lightweight, modular architectural style, microservices can split complex applications into smaller, independent service units, providing better scalability, reliability and maintainability through mutual cooperation. This article will introduce how to design a high-performance PHP microservice architecture and provide specific code examples. 1. Split microservices Before designing a high-performance PHP microservice architecture,

Website Security Architecture Design Guide: Implementation of PHP Firewall Introduction: In today's Internet era, website security problems are becoming increasingly serious. Hackers are constantly using loopholes to invade websites, steal user information or disrupt the normal operation of the website. In order to protect the privacy and security of the website and its users, it is crucial to establish a reliable security architecture. This article will focus on the implementation of PHP firewall and provide guidance for website security architecture. 1. What is a PHP firewall? The PHP firewall is a security measure that blocks malicious attacks and intrusions by filtering
