jQuery原理第二天

jQuery原理

今天手動實現了以下方法

jQ原型上的核心方法和屬性:

​ 1、jquery 獲取jQ版本號

​ 2、selector 實例默認的選擇器取值

​ 3、length 實例默認的長度

​ 3、push 給實例添加新元素

​ 4、sort 對實例中的元素進行排序

​ 5、splice 按照指定下標指定數量刪除元素,也可以替換刪除的元素

​ 6、toArray 把實例轉換爲數組返回

​ 7、get 獲取指定下標的元素,獲取的是原生DOM

​ 6、eq 獲取指定下標的元素,獲取的是jQuery類型的實例對象

​ 7、first 獲取實例中的第一個元素,是jQuery類型的實例對象

​ 8、last 獲取實例中的最後一個元素,是jQuery類型的實例對象

​ 9、each 遍歷實例,把遍歷到的數據傳給回調使用

​ 10、map 遍歷實例,把遍歷到的數據傳給回調使用,然後把回調的返回值收集起來組成一個新的數組返回

jQuery的extend方法

<!--
 * @Author: 碼小余
 * @Date: 2020-06-24 10:33:33
 * @LastEditTime: 2020-06-24 10:40:02
 * @FilePath: \代碼\jQuery原理\04-jQuery的extend方法.html
-->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>04-jQuery的extend方法</title>
    <script>
      function njQuery() {}
      /*
      njQuery.extend = function (obj) {
        // 此時此刻的this就是njQuery這個類
        // console.log(this);
        for (var key in obj) {
          // njQuery["isTest"] = function () {console.log("test");}
          this[key] = obj[key];
        }
      };
      njQuery.extend({
        isTest: function () {
          console.log("test");
        },
      });
      njQuery.isTest();
      */
      /*
      njQuery.prototype.extend = function (obj) {
        // 此時此刻的this是njQuery對象
        // console.log(this);
        for (var key in obj) {
          // q["isDemo"] = function () {console.log("demo");}
          this[key] = obj[key];
        }
      };
      var q = new njQuery();
      q.extend({
        isDemo: function () {
          console.log("demo");
        },
      });
      q.isDemo();
      */
      // 合併
      njQuery.extend = njQuery.prototype.extend = function (obj) {
        // console.log(this);
        for (var key in obj) {
          this[key] = obj[key];
        }
      };
      // njQuery.extend({});
      var q = new njQuery();
      q.extend({});
    </script>
  </head>
  <body></body>
</html>

jQuery監聽DOM加載

<!--
 * @Author: 碼小余
 * @Date: 2020-06-24 11:25:38
 * @LastEditTime: 2020-06-24 11:26:15
 * @FilePath: \代碼\jQuery原理\05-jQuery監聽DOM加載.html
-->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script src="js/njQuery-1.0.0.js"></script>
    <script>
      /*
        onload事件會等到DOM元素加載完畢, 並且還會等到資源也加載完畢纔會執行
        DOMContentLoaded事件只會等到DOM元素加載完畢就會執行回調
        */
      /*
        window.onload = function (ev) {
            // var res = document.querySelectorAll("div");
            // console.log(res);
            console.log("onload");
        }
        document.addEventListener("DOMContentLoaded", function () {
            // var res = document.querySelectorAll("div");
            // console.log(res);
            console.log("DOMContentLoaded");
        });
        */
      /*
        document.readyState屬性有如下的狀態
        uninitialized - 還未開始載入
        loading - 載入中
        interactive - 已加載,文檔與用戶可以開始交互
        complete - 載入完成

        onreadystatechange事件就是專門用於監聽document.readyState屬性的改變的
        */
      /*
        document.attachEvent("onreadystatechange", function () {
            if(document.readyState == "complete"){
                console.log("onreadystatechange");
            }
        });
        */
      $(function () {
        var res = document.querySelectorAll("div");
        console.log(res);
      });
    </script>
  </head>
  <body>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
  </body>
</html>

代碼記錄:

/*
 * @Author: 碼小余
 * @Date: 2020-06-23 09:26:25
 * @LastEditTime: 2020-06-24 13:30:21
 * @FilePath: \代碼\jQuery原理\js\njQuery-1.1.0.js
 */
(function (window, undefined) {
  function njQuery(selector) {
    return new njQuery.prototype.init(selector);
  }
  njQuery.prototype = {
    constructor: njQuery,
    init: function (selector) {
      /*
         1.傳入 '' null undefined NaN  0  false, 返回空的jQuery對象
         2.字符串:
         代碼片段:會將創建好的DOM元素存儲到jQuery對象中返回
         選擇器: 會將找到的所有元素存儲到jQuery對象中返回
         3.數組:
         會將數組中存儲的元素依次存儲到jQuery對象中立返回
         4.除上述類型以外的:
         會將傳入的數據存儲到jQuery對象中返回
        */

      // 0. 去除字符串兩端的空格
      selector = njQuery.trim(selector);

      // 1.傳入 '' null undefined NaN  0  false, 返回空的jQuery對象
      if (!selector) {
        // return this;
      }
      // 2. 方法處理
      else if (njQuery.isFunction(selector)) {
        njQuery.ready(selector);
      }
      // 2. 字符串
      else if (njQuery.isString(selector)) {
        // 2.1. 判斷是否是代碼片段
        if (njQuery.isHTML(selector)) {
          // 1. 根據代碼片段創建所有的元素
          var temp = document.createElement("div");
          temp.innerHTML = selector;
          //   // 2. 將創建好定得一級元素添加到jQuery當中
          //   for (var i = 0; i < temp.children.length; i++) {
          //     this[i] = temp.children[i];
          //   }
          //   // 3. 給jQuery對象添加length屬性
          //   this.length = temp.children.length;
          [].push.apply(this, temp.children);
          // 4. 返回加工好的this(jQuery)
          // return this;
        }
        // 2.2 判斷是否是選擇器
        else {
          // 1. 根據傳入的選擇器找到對應的元素
          var res = document.querySelectorAll(selector);
          //   // 2. 將找到的元素添加到njQuey上
          //   for (var i = 0; i < res.length; i++) {
          //     this[i] = res[i];
          //   }
          //   this.length = res.length;
          [].push.apply(this, res);
          // 3. 返回加工好的this
          // return this;
        }
      }
      // 3. 數組
      else if (njQuery.isArray(selector)) {
        /*
        // 3.1 真數組
        if ({}.toString.apply(selector) === "[object Array]") {
          // 將真數組轉成僞數組
          [].push.apply(this, selector);
          return this;
        }
        // 3.2 僞數組
        else {
          // 先將自定義的僞數組轉成真數組
          var arr = [].slice.apply(selector);
          // 在將真數組轉成僞數組
          [].push.apply(this, arr);
          return this;
        }
        */
        var arr = [].slice.apply(selector);
        [].push.apply(this, arr);
        // return this;
      }
      // 4. 除上述類型以外
      else {
        this[0] = selector;
        this.length = 1;
        // return this;
      }
      return this;
    },
    jquery: "1.1.0",
    selector: "",
    length: 0,
    // [].push找到數組的push方法
    // 冒號前面的push將來由njQuery對象調用
    // 相當於 [].push.apply(this);
    push: [].push,
    sort: [].sort,
    splice: [].splice,
    toArray: function () {
      return [].slice.apply(this);
    },
    get: function (num) {
      // 沒有傳遞參數
      if (arguments.length === 0) {
        return this.toArray();
      }
      // 傳遞不是負數
      else if (num >= 0) {
        return this[num];
      }
      // 傳遞負數
      else {
        return this[this.length + num];
      }
    },
    eq: function (num) {
      // 沒有傳遞參數
      if (arguments === 0) {
        return new njQuery();
      } else {
        return new njQuery(this.get(num));
      }
    },
    first: function () {
      return this.eq(0);
    },
    last: function () {
      return this.eq(-1);
    },
    each: function (fn) {
      return njQuery.each(this, fn);
    },
  };
  njQuery.extend = njQuery.prototype.extend = function (obj) {
    for (var key in obj) {
      this[key] = obj[key];
    }
  };
  njQuery.extend({
    // 是不是字符串
    isString: function (str) {
      return typeof str === "string";
    },
    // 是不是HTML代碼片段
    isHTML: function (str) {
      return (
        str.charAt(0) == "<" &&
        str.charAt(str.length - 1) == ">" &&
        str.length >= 3
      );
    },
    // 去除字符串兩端空格
    trim: function (str) {
      if (!njQuery.isString(str)) {
        return str;
      }
      // 判斷是否支持trim方法
      if (str.trim) {
        return str.trim();
      } else {
        return str.replace(/^\s+|\s+$/g, "");
      }
    },
    // 是不是對象
    isObject: function (sele) {
      return typeof sele === "object";
    },
    // length屬性是否存在
    beLength: function (sele) {
      return "length" in sele;
    },
    // 是不是windw對象
    isWindow: function (sele) {
      return sele === window;
    },
    // 是不是數組
    isArray: function (sele) {
      if (
        njQuery.isObject(sele) &&
        njQuery.beLength(sele) &&
        !njQuery.isWindow(sele)
      ) {
        return true;
      }
      return false;
    },
    isFunction: function (sele) {
      return typeof sele === "function";
    },
    ready: function (fn) {
      // 判斷DOM是否加載完畢
      if (document.readyState === "complete") {
        fn();
      } else if (document.addEventListener) {
        document.addEventListener("DOMContentLoaded", function () {
          fn();
        });
      } else {
        document.attachEvent("onreadystatechange", function () {
          if (document.readyState === "complete") {
            fn();
          }
        });
      }
    },
    each: function (obj, fn) {
      // 1.判斷是否是數組
      if (njQuery.isArray(obj)) {
        for (var i = 0; i < obj.length; i++) {
          var res = fn.call(obj[i], i, obj[i]);
          if (res === true) {
            continue;
          } else if (res === false) {
            break;
          }
        }
      }
      // 2.判斷是否是對象
      else if (njQuery.isObject(obj)) {
        for (key in obj) {
          var res = fn.call(obj[key], key, obj[key]);
          if (res === true) {
            continue;
          } else if (res === false) {
            break;
          }
        }
      }
      return obj;
    },
    map: function (obj, fn) {
      var res = [];
      // 1.判斷是否是數組
      if (njQuery.isArray(obj)) {
        for (var i = 0; i < obj.length; i++) {
          var temp = fn(obj[i], i);
          if (temp) {
            res.push(temp);
          }
        }
      }
      // 2.判斷是否是對象
      else if (njQuery.isObject(obj)) {
        for (var key in obj) {
          var temp = fn(obj[key], key);
          if (temp) {
            res.push(temp);
          }
        }
      }
      return res;
    },
  });

  njQuery.prototype.init.prototype = njQuery.prototype;
  window.njQuery = window.$ = njQuery;
})(window);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章