This introduction

This series is used to document my study of jQuery source code, study version is V2.1.4. The purpose is twofold, one is to record the learning process, the other is to share the learning experience and understanding. The reason to learn JQ source code, although there are modern front-end frameworks like Vue, React, NG, but JQ design ideas are never out of date, so I want to explore.

The overall structure

The jQuery code looks like this:

(function(global, factory) {
  // module Determines the export mode
  factory(global); } (typeof window! = ="undefined" ? window : this.function(window, noGlobal) {
    // Define some private variables
    // init
    // extend
    // extend functions
    // sizzle
    // callbacks
    // deferred
    // data
    // dom css attr
    // event
    // ajax
    // animation
    return jQuery
}))
Copy the code

The inside function body is wrapped in an immediate function, which is designed to prevent code in the body from contaminating the global code, and to prevent code outside of the body from modifying internal methods, except for exposed interfaces.

  1. The advantage of passing an external window internally by executing a function immediately is that you don’t need to find the global window, which is easy to compress, and is internally compressed to W.
  2. Pass in a factory function to the immediate execution function, and let the internal determine how to export and execute the function.

Inside the factory function, the functional modules are separated to make the architecture appear orderly, which is divided into plug-in module, selector module, callback function management module, delay object module, data management module, event module, Ajax, animation and CSS, and property module.

The last line of the factory function returns the jQuery object.

Initialize the constructor

In the first section of the factory function, we define some variables

var arr = [];
var slice = arr.slice;
var concat = arr.concat;
varpush = arr.push; .var version = 2.1.4 "",
    jQuery = function (selector, context) {
      return new jQuery.fn.init(selector, context)
    }
...
Copy the code

Methods for defining native arrays and objects are designed for easy management and compression, as above. There are several utility functions for whitespace, compatibility, hump, etc. The most important one is the jQuery function.

The jQuey function takes two arguments, a selector and a context. Return an instance object, as you can see, constructed from jquery.fn.init (). The real constructor is jquery.fn.init ().

jQuery.fn = jQuery.prototype = {}

jQuery.fn = jQuery.prototype = {
  jquery: version,
  constructor: jQuery,
  ...
  toArray: function () {
    return slice.call(this);
  },
  get(){... },each(){... },map(){...},
  ...
}
Copy the code

This code overwrites the jQuery prototype, so modify the constructor to point to constructor: jQuery, or instantiate it to point to Object. Then add the version attribute to the prototype object and add some common transform arrays, such as slice, push, sort, splice, map, etc.

The benefit of jQuery is that it is automatically instantiated when you call jQuery or $, making it easy to manipulate and chain calls.

The init method is added externally to the prototype (line 2765 of source code):

var init = jQuery.fn.init = function (selector, context) {... }Copy the code

Inside is to check whether the selector is valid:

if(! selector)return this;
if (typeof selector === "string") {... }else if (selector.nodeType) {
  ...
} else if (jQuery.isFunction(selector)) {
  ...
}
Copy the code
init.prototype = jQuery.fn;
Copy the code

This line of code is the key to direct instantiation.

This way you can directly instantiate and have all the methods on jQuery.

Plug-ins and extensions to some tool methods

jQuery.extend = jQuery.fn.extend = function () {... returntarget; }Copy the code
var options, name, src, copy, copyIsArray, clone,
    target = arguments[0] || {},
    i = 1,
    length = arguments.length,
    deep = false;
Copy the code

Extend adds static methods to jQuery itself or to prototypes. Adding methods by extension makes the architecture more manageable.

Source code implementation, first made a judgment:

// Whether it is a deep copy
if (typeof target === "boolean") {
  deep = target;
  target = arguments[i] || {};
  i++;
}
// Assign objects to functions that are not objects
if (typeoftarget ! = ="object" && !jQuery.isFunction(target)) {
  target = {};
}
// There is only one argument
if (i === length) {
  target = this;
  i--;
}
Copy the code

If there are multiple objects:

for (; i < length; i++) {
  if (target === copy) { continue; } // Prevent circular references
  if () {} / / copy
  else if () {} / / shallow copy
}
Copy the code

If you look at the detailed implementation it’s line 176 of the source code

Add static methods (source line 241)

More than ten tool methods such as Error, isFunction, isArray, isNumeric, isEmptyObject, makeArray, grep are added, which will not be explained in detail here.

conclusion

This article covers the basic architecture and initialization of jQuery, and the next one covers callback event management and deferred object management, learning about the idea of observing patterns and event queues.