Home  >  Article  >  Web Front-end  >  What you need to know about the use of JavaScript "jquery inheritance" (detailed code explanation)

What you need to know about the use of JavaScript "jquery inheritance" (detailed code explanation)

奋力向前
奋力向前forward
2021-08-19 11:49:362163browse

In the previous article "In-depth analysis of the array reduce method in JS (with code)", I will give you an understanding of the array reduce method in JS. The following article will teach you how to use jquery in JS-inheritance. Friends can refer to it.

What you need to know about the use of JavaScript

jqueryAs of now, it is version 3.3.1. Nowadays, with the popularity of various browsers, front-end frameworks are emerging in endlessly. jquery is unique in the world. I only use jquery when writing code. The glorious era of just picking up the code and doing it has passed.

In 2006, the first version of jQuery was released. It was loved by developers for its concise and flexible programming style. And it itself is a JavaScript framework. Its design purpose is "write Less, Do More", that is, it advocates writing less code and doing more. Many things. It encapsulates JavaScript commonly used function codes, provides a simple JavaScript design pattern, and optimizes HTML document operations, event processing, animation design and Ajaxinteraction.

From being popular before to being abandoned now, many front-end engineers said that for jQuery, although a large number of operations DOM are convenient, But it will sacrifice a lot of page performance. On the other hand, at this stage, mainstream front-end frameworks such as React, Vue and Angularjs do not rely on jQuery and can be used independently. Moreover, there are fewer and fewer browser compatibility issues. When browser compatibility is no longer a problem, the value of jQuery will be greatly reduced.

On the 52nd day after Microsoft acquired github, github The change has also been abandoned jquery, the odd alternative uses the native js:

  • uses querySelectorAll to query DOM nodes;

  • Use fetch instead of ajax;

  • Event processing uses event proxies;

  • Using DOM standardization to write polyfill;

  • Custom elements are used.

What you need to know about the use of JavaScript jquery inheritance (detailed code explanation)

If you don’t use it, you can still learn it

This article is a rough implementationjqueryready, each, bind, ``$.fn.extend, $.extend

Initialization$

(function (win) {
  var _$ = function (selector, context) {
    /**
     * 通常咱们定义一个 函数 var Fun = function(){}
     * 然后定义一个 Fun.prototype.init = function(){}
     * 那么咱们调用init 的时候 得先要实例化对象 var f = new Fun()
     * 然后f.init()
     * 这里就省去了 var $ = new $()
     */
    return new _$.prototype.Init(selector, context);
  };
  _$.prototype = {
    //初始化$
    Init: function (selector, context) {
      this.elements = [];
      /**
       * 传入的类型是function 就执行ready事件,如果是document 就将document对象插入到this.elements
       * 主要就是判断$(document).ready  和 $(function(){}) 这两种的ready事件的写法
       */
      if (typeof selector === "function") {
        this.elements.push(document);
        this.ready(selector);
      } else {
        var context = context || document;
        var isDocument = (ele) =>
          Object.prototype.toString.call(ele) == "[object HTMLDocument]" ||
          "[object Document]";
        if (isDocument(selector)) {
          this.elements.push(selector);
        } else {
          /**
           * 如果是字符串的话就查询该节点 $('.class') | $('#id')
           */
          if (context.querySelectorAll) {
            var arr = context.querySelectorAll(selector);
            for (var i = 0; i < arr.length; i++) {
              this.elements.push(arr[i]);
            }
          }
        }
      }
    },
    //实现each
    each: function (callback) {},
    //实现ready
    ready: function (callback) {},
    //实现bind
    bind: function (type, callback) {},
  };
  /**
   * 让两个作用域不一样的对象共享一个方法,让他们的原型指向一致,即Init.prototype = _$.prototype
   * 那么原型一致之后 就可以共享this.elements 属性了。
   */
  _$.prototype.Init.prototype = _$.prototype;
  window.$ = _$;
})(window || global);

ready

//实现ready
ready: function (callback) {
  var isDocument = (ele) => Object.prototype.toString.call(ele) == &#39;[object HTMLDocument]&#39; || &#39;[object Document]&#39;
  //如果已经取得了节点
  if (isDocument(this.elements[0])) {
    if (document.addEventListener) { //判断火狐、谷歌
      /**
       * DOM树构建完成的时候就会执行DOMContentLoaded
       * 页面上所有的DOM,样式表,脚本,图片,flash都已经加载完成了,才会触发window.onload
       * 这也就是$(document).ready() 比 window.onload 执行早的原因
       *
       * arguments.callee 博客里面有一篇文章 [js-递归] 里面专门讲到了,这里不再解释了
       */
      document.addEventListener(&#39;DOMContentLoaded&#39;, function () {
        document.removeEventListener(&#39;DOMContentLoaded&#39;, arguments.callee, false)
        callback()
      }, false)
    } else if (document.attachEvent) { //判断IE
      document.attachEvent(&#39;onreadystatechange&#39;, function () {
        if (document.readyState == &#39;complete&#39;) {
          document.detachEvent(&#39;onreadystatechange&#39;, arguments.callee);
          callback()
        }
      })
    } else if (document.lastChild == document.body) { //body已经加载完了,就直接回调了
      callback()
    }
  }
},

each

//实现each
 each: function (callback) {
    if (this.elements.length > 0) {
        for (var i = 0; i < this.elements.length; i++) {
        callback.call(this, this.elements[i], i);
        }
    }
 },

bind

//实现bind
bind: function (type, callback) {
  if (document.addEventListener) { //判断火狐、谷歌
    this.each(function (item, i) {
        item.addEventListener(type, callback, false)
    })
    } else if (document.attachEvent) { //判断IE
    this.each(function (item, i) {
        item.attachEvent(&#39;on&#39; + type, callback)
    })
    } else {
    this.each(function (item, i) { //其他浏览器 egg: item.onclick = function(){}
        item[&#39;on&#39; + type] = callback
    })
  }
}

$.fn.extend/$.extend

$.fn.extend is an extension method for the query node object, which is based on $ The prototype extension method

$.extend is an extension regular method and a static method of $

The official explanation is:

jQuery.extend(): Merge the contents of two or more objects together into the first object. (Merge two or more objects into the first one)

jQuery.fn.extend():Merge the contents of an object onto the jQuery prototype to provide new jQuery instance methods. (Mount the object into jQueryprototypeAttribute, to extend a new jQuery instance method)

$.fn.extendThe original intention of the method is that we can use $( "").newMetod()Accessing in this way is actually adding an extend method to the $ prototype. The fn in the middle is actually similar to the role of a namespace and has no practical significance. To distinguish it from $.extend

$.fn.extend

; (function (win) {
  ...
  _$.prototype.Init.prototype = _$.prototype;

   _$.fn = _$.prototype; //把对象挂载到jQuery的prototype属性

  var isObj = (o) => Object.prototype.toString().call(o) === &#39;[object Object]&#39;;
  $.fn.extend = function (obj) {
    if (isObj(obj)) {
      for (var i in obj) {
        this[i] = obj  //注意这里的this指向是 $.prototype
      }
    }
  }

$.extend

var isObj = (o) => Object.prototype.toString().call(o) === &#39;[object Object]&#39;;
...
_$.extend = function (obj) {
    if (isObj(obj)) {
        for (var i in obj) {
            this[i] = obj[i]; //注意这里的this指向是 $
        }
    }
}

These two look exactly the same, there is no difference. As mentioned in the comments, this points to different points. Let’s take a look at an example:

<!DOCTYPE html>
<html>
  <head>
    <title>jQuery.extend()与jQuery.fn.extend()区别</title>
    <meta charset="utf-8" />
    <script type="text/javascript" src="jquery.js"></script>
    <!-- 开始扩展 -->
    <script type="text/javascript">
      (function ($) {
        $.extend({
          sayHello: function () {
            console.log("Hello");
          },
        });
        $.fn.extend({
          sayHello: function () {
            console.log("Hello");
          },
        });
      })(jQuery);
    </script>
    <!-- 调用 -->
    <script type="text/javascript">
      $(document).ready(function () {
        //$.extend扩展调用
        $.sayHello();

        //$.fn.extend扩展调用
        $("#test").sayHello();
      });
    </script>
  </head>
  <body>
    <div id="test"></div>
  </body>
</html>

Now it’s clear. jQuery.extend(object); To extend the jQuery class itself, add new methods to itself. $.xxx()

jQuery.fn.extend(object);Add methods to jQuery objects$('# test').xxx()

##$.extendCommon usage

//在jquery全局对象中扩展一个net命名空间。
$.extend({ net: {} });

//方法扩展到之前扩展的Jquery的net命名空间中去。
$.extend($.net, {
  sayHello: function () {
    console.log("Hello");
  },
});

//extend方法还有一个重载原型
//extend(boolean,dest,src1,src2,src3...),第一个参数boolean代表是否进行深度拷贝
var a = { protocol: "http", hash: { a: 1, b: 2 } };
var b = { host: "chuchur.com", hash: { b: 1, c: 2 } };

var result = $.extend(true, {}, a, b);
console.log(result); //{ protocol: &#39;http&#39;,host: &#39;chuchur.com&#39;, hash: { a: 1, b: 1,c:2 } }

var result = $.extend(false, {}, a, b);
console.log(result); //{ protocol: &#39;http&#39;,host: &#39;chuchur.com&#39;, hash: { b: 1, c:2 } }

Complete code

(function (win) {
  var _$ = function (selector, context) {
    /**
     * 通常咱们定义一个 函数 var Fun = function(){}
     * 然后定义一个 Fun.prototype.init = function(){}
     * 那么咱们调用init 的时候 得先要实例化对象 var f = new Fun()
     * 然后f.init()
     * 这里就省去了 var $ = new $()
     */
    return new _$.prototype.Init(selector, context);
  };
  _$.prototype = {
    //初始化$
    Init: function (selector, context) {
      this.elements = [];
      /**
       * 传入的类型是function 就执行ready事件,如果是document 就将document对象插入到this.elements
       * 主要就是判断$(document).ready  和 $(function(){}) 这两种的ready事件的写法
       */
      if (typeof selector === "function") {
        this.elements.push(document);
        this.ready(selector);
      } else {
        var context = context || document;
        var isDocument = (ele) =>
          Object.prototype.toString.call(ele) == "[object HTMLDocument]" ||
          "[object Document]";
        if (isDocument(selector)) {
          this.elements.push(selector);
        } else {
          /**
           * 如果是字符串的话就查询该节点 $(&#39;.class&#39;) | $(&#39;#id&#39;)
           */
          if (context.querySelectorAll) {
            var arr = context.querySelectorAll(selector);
            for (var i = 0; i < arr.length; i++) {
              this.elements.push(arr[i]);
            }
          }
        }
      }
    },
    //实现each
    each: function (callback) {
      if (this.elements.length > 0) {
        for (var i = 0; i < this.elements.length; i++) {
          callback.call(this, this.elements[i], i);
        }
      }
    },
    //实现ready
    ready: function (callback) {
      var isDocument = (ele) =>
        Object.prototype.toString.call(ele) == "[object HTMLDocument]" ||
        "[object Document]";
      //如果已经取得了节点
      if (isDocument(this.elements[0])) {
        if (document.addEventListener) {
          //判断火狐、谷歌
          /**
           * DOM树构建完成的时候就会执行DOMContentLoaded
           * 页面上所有的DOM,样式表,脚本,图片,flash都已经加载完成了,才会触发window.onload
           * 这也就是$(document).ready() 比 window.onload 执行早的原因
           *
           * arguments.callee 博客里面有一篇文章 js-递归里面专门讲到了,这里不再解释了
           */
          document.addEventListener(
            "DOMContentLoaded",
            function () {
              document.removeEventListener(
                "DOMContentLoaded",
                arguments.callee,
                false
              );
              callback();
            },
            false
          );
        } else if (document.attachEvent) {
          //判断IE
          document.attachEvent("onreadystatechange", function () {
            if (document.readyState == "complete") {
              document.detachEvent("onreadystatechange", arguments.callee);
              callback();
            }
          });
        } else if (document.lastChild == document.body) {
          //body已经加载完了,就直接回调了
          callback();
        }
      }
    },
    //实现bind
    bind: function (type, callback) {
      if (document.addEventListener) {
        //判断火狐、谷歌
        this.each(function (item, i) {
          item.addEventListener(type, callback, false);
        });
      } else if (document.attachEvent) {
        //判断IE
        this.each(function (item, i) {
          item.attachEvent("on" + type, callback);
        });
      } else {
        this.each(function (item, i) {
          //其他浏览器 egg: item.onclick = function(){}
          item["on" + type] = callback;
        });
      }
    },
  };
  /**
   * 让两个作用于不一样的对象共享一个方法,让他们的原型指向一直,即Init.prototype = _$.prototype
   * 那么指向之后 就可以共享this.elements 属性了。
   */
  _$.prototype.Init.prototype = _$.prototype;

  var isObj = (o) => Object.prototype.toString().call(o) === "[object Object]";
  $.fn.extend = function (obj) {
    if (isObj(obj)) {
      for (var i in obj) {
        this[i] = obj; //注意这里的this指向是 $.prototype
      }
    }
    //....这里是简写
  };

  _$.extend = function (obj) {
    if (isObj(obj)) {
      for (var i in obj) {
        this[i] = obj[i]; //注意这里的this指向是 $
      }
    }
    //....这里是简写
  };

  window.$ = _$;
})(window || global);

【End】

Recommended learning:

jQuery video tutorial

The above is the detailed content of What you need to know about the use of JavaScript "jquery inheritance" (detailed code explanation). For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:chuchur.com. If there is any infringement, please contact admin@php.cn delete