了解 jQuery 的内部工作原理

mav*_*ick 5 javascript jquery

所以我试图了解jQuery内部是如何运作的。jQuery公开一个全局$变量,可以像这样使用:

$('.abc') // returns a list of DOM nodes having class abc
$.ajax() // used to perform AJAX requests
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,$在语句 1 中它是一个函数,在语句 2 中它是一个对象。现在我知道这是可能的,因为function Objects在 JavaScript 中,这意味着函数Object在 JavaScript 中也是 an ,因此你可以附加方法到它。但我不确定内部是如何实现的?

我正在看这篇博客文章,它解释了如何使用“构造函数模式”来模仿 jQuery,但是如何在$使用该模式时附加方法呢?或者 jQuery 使用一些完全不同的模式?这是 jQuery 的一个小实现。这段代码可以实现$(selector),但是如何添加呢$.method?

$('.abc') // returns a list of DOM nodes having class abc
$.ajax() // used to perform AJAX requests
Run Code Online (Sandbox Code Playgroud)
// Mini jQuery implementation 
var $ = (function() {
  var JQuery = function(selector) {
    if (selector === "document") {
      this.elements = [document];
    } else if (selector === "window") {
      this.elements = [window];
    } else {
      this.elements = document.querySelectorAll(selector);
    }
    return this;
  };

  JQuery.prototype.each = function(callback) {
    this.elements.forEach(function(element) {
      callback(element);
    });
    return this;
  };

  JQuery.prototype.addClass = function() {
    if (arguments.length === 0) return this;
    else {
      this.each(element => {
        element.classList.add(...arguments);
      });
      return this;
    }
  };

  return function(selector) {
    return new JQuery(selector);
  };
})();

// Use our mini jQuery to turn background of matching Nodes green
$(".abc").addClass("highlight");
Run Code Online (Sandbox Code Playgroud)
.abc {
  background : red;
}

.abc.highlight {
  background: green;
}
Run Code Online (Sandbox Code Playgroud)

Sha*_*ani 4

构造函数模式实际上并没有解决问题$.method,如果你想实现$.method你必须稍微解决一下,这是一个基于你的例子的简单解决方案:

var $ = (function() {
  
  var JQuery = function(selector) {
    if (selector === "document") {
      this.elements = [document];
    } else if (selector === "window") {
      this.elements = [window];
    } else {
      this.elements = document.querySelectorAll(selector);
    }
    return this;
  };

  JQuery.prototype.each = function(callback) {
    this.elements.forEach(function(element) {
      callback(element);
    });
    return this;
  };

  JQuery.prototype.addClass = function() {
    if (arguments.length === 0) return this;
    else {
      this.each(element => {
        element.classList.add(...arguments);
      });
      return this;
    }
  };

  return function(selector) {
    
    // A simple function for extending object properties/values to another object
    $.extend = JQuery.prototype.extend = function(source) {
      if (typeof arguments[0] !== 'object') return;

      for (var prop in source) {
        if (source.hasOwnProperty(prop)) {
          this[prop] = source[prop];
        }
      }
    };
    
    // Extend all the JQuery prototype methods to the '$' object
    $.extend(JQuery.prototype);
    
    // Others extensions that's can only accessed via '$.method' and not '$('selector').method'
    $.extend({
      ajax: function() {},
      noop: function() {},
    });
    
    return new JQuery(selector);
  };
})();

// Use our mini jQuery to turn background of matching Nodes green
$("body").addClass("highlight");
$.addClass.call($('body'), 'selected');
Run Code Online (Sandbox Code Playgroud)

jQuery 不使用$orjQuery对象的构造函数模式,如果你检查这个,你可以看到它$只是这里定义的init 函数的构造函数jQuery,所有初始化的 jQuery 对象方法都附加到( 的别名) (这是此处的一个示例),其他方法如、、直接附加到对象(此处是 ajax 方法的示例)。这就是为什么我们可以使用语法访问这些方法。jQuery.fn.init$("body")jQuery.fnjQuery.prototypeajaxnoopisReady$$.method

抱歉我的英语不好,我希望这对你有意义。

Edit1:对于任何对 jQuery 内部工作方式感兴趣并想了解更多有关 jQuery 核心的人,我特别为此目的创建了这个 github 存储库how-jQuery-work 。谢谢!