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);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章