JavaScript 原型的實際應用之實現一個 jQuery

咱們平時使用jQuery大概是這樣:css

let $p = $('p');
$p.css('fontSize', '40px');

咱們生成jQuery實例對象後,就能夠使用原型上的css(), html()等方法,這就體現了原型繼承:由構造函數生成的實例對象,能夠繼承構造函數的原型對象上的屬性和方法。html

咱們能夠試着手寫一個迷你的jQuery,思路大概是這樣:node

1-經過匿名自執行函數來存放咱們的代碼,將window對象做爲參數傳入,防止全局做用域的污染。jquery

2-利用工廠函數,在調用jQuery或者$的時候,返回構造函數的實例對象git

3-構造函數定義爲jQuery.fn.init,初始化時處理dom元素,將dom元素綁定在實例對象上github

4-將構造函數的prototype屬性指向jQuery.fn,此時構造函數的實例即可以繼承jQuery.fn裏的屬性和方法dom

5-jQuery.fn是一個對象,裏面存放了全部的jQuery方法,讓外部來調用函數

代碼實現:
完整代碼請查看 my-jquery測試

// my-jquery.js

(function(window) {
  var jQuery = function (selector) {
    // 經過new關鍵字,找到構造函數
    return new jQuery.fn.init(selector);
  };

  // 初始化 jQuery.fn
  jQuery.fn = jQuery.prototype =  {
    constructor: jQuery,
    css: function(key, value) {
      let that = this;
      for (var i = 0; i < that.length; i++) {
        that[i].style[key] = value;
      }
    },
    html: function (value) {
      return this[0].innerHTML;
    },
  };

  // 定義構造函數
  var init = jQuery.fn.init = function(selector) {
    var slice = Array.prototype.slice;
    var dom = slice.call(document.querySelectorAll(selector));
    var i,
      len = dom ? dom.length : 0;
    for (i = 0; i < len; i++) {
      this[i] = dom[i];
    }
    this.length = len;
    this.selector = selector || '';
  };

  // 定義原型
  init.prototype = jQuery.fn;

  window.$ = jQuery;
})(window);

這裏有個問題:這裏爲何不直接把init.prototype賦值爲一個對象,而是要經過jQuery.fn作中轉呢?this

jQuery.fn = {...};

init.prototype = jQuery.fn;

這就體現了原型的擴展性,jQuery.fn | $.fn 是用來擴展插件用的,將插件擴展統一到$.fn.xxx 這一個接口,也是符合對修改封閉,對擴展開放的原則。

下面咱們來寫一個簡單的jQuery插件。

$.fn.getNodeName = function () {
    return this[0].nodeName;
}

// 測試
alert($box.getNodeName()); // DIV

小結:

本篇文章總結了如下幾個問題

  • jQuery是如何使用原型的?
  • 如何實現一個小型的jQuery?
  • jQuery的插件擴展機制
相關文章
相關標籤/搜索