美文网首页
jQuery 源码解析——无new构建实例和extend方法

jQuery 源码解析——无new构建实例和extend方法

作者: 我是Msorry | 来源:发表于2021-03-23 19:06 被阅读0次

    无 new 构建实例

    $ 是 jQuery 的别称,$() 是创建 jQuery 的实例对象

    共享原型设计

    jQuery 选择一个折中的方案,当调用 $() 时,就会在 jQuery 原型上面的 jQuery.prototype.init 方法,把 init 方法当做构造函数返回实际的对象;现在想要创建 jQuery 的实例对象,但是在 jQuery 原型上面扩展的方法也会被继承;jQuery 用到一个共享原型的设计,让 jQuery 原型对象的 init 方法和 jQuery 共享

    jQuery.prototype.init 作为构造函数,因为有共享原型对象的存在,jQuery.prototype.init.prototype 指向 jQuery.prototype ,所以 jQuery.prototype.init 构造的对象也指向 jQuery

    $() 创建的是 jQuery 原型上 init 的实例对象,并不是 jQuery 的实例对象,但是 jQueryjQuery.prototype.init 共享原型,所以 $() 指向 jQuery

    源码解析

    !(function (root) {
      let jQuery = function () {
        return new jQuery.prototype.init()
      }
      jQuery.prototype = {
        init:function (){},
      }
    
      // 共享原型对象
      jQuery.prototype.init.prototype = jQuery.prototype
    
      root.$ = root.jQuery = jQuery
    })(this)
    

    extend 方法

    功能
    1. 外部使用:将两个或者更多个对象合并到第一个对象

    jQuery.extend(target, object1 [,objectN]),返回合并后的 target

    // 浅拷贝,常用的插件开发模式
    let defaults = { validate: false, limit: 5, name: "foo" };
    let options = { validate: true, name: "bar" };
    
    let settings = $.extend({}, defaults, options);
    
    // 深拷贝
    let object1 = {
      apple: 0,
      banana: {weight: 52, price: 100},
      cherry: 97
    };
    let object2 = {
      banana: {price: 200},
      durian: 100
    };
     
    /* merge object2 into object1, recursively */
    $.extend(true, object1, object2);
    
    2. 内部使用:扩展 jQuery 自身
    $.extend({
      foo:function(){}
    })
    
    jQuery.foo()
    

    扩展 jQuery 实例对象

    $.fn.extend({
      sex:"female"
    })
    $().sex //female
    
    源码实现

    extend 方法可以通过 $.extend$.fn.extend 两种方式调用,二者实际上调用的是同一个函数

      // extend
      jQuery.fn.extend = jQuery.extend = function () {
        // 获取目标
        let target = arguments[0] || {}
        // 获取参数长度
        let length = arguments.length
        // 参数数组索引
        let i = 1
        // target的扩展定义为option
        let option
        // 判断深拷贝
        let deep = false
        // 用于拆分浅拷贝和深拷贝
        let copy, src
        // 判断数组类型
        let copyIsArray
        // 用于递归运算
        let clone
    
        if (typeof target === "boolean") {
          deep = target
          target = arguments[1] || {}
          ++i
        }
    
    
        // 当目标对象值类型错误,则重置为{}
        if (typeof target !== "object") {
          target = {}
        }
        // 参数长度为1时,目标对象为自身
        if (length === i) {
          target = this
          --i
        }
        // 浅拷贝
        for (; i < length; i++) {
          option = arguments[i]
          // 忽略null 和 undefined
          if ((options = arguments[ i ]) != null) {
            for (let key in option) {
              // 保存复制值,因此扩展jquery自身只能在copy之后使用
              copy = option[key]
              // 保存目标对象自身值
              src = target[key]
              // 防止环引用
              if ( target === copy ) {
                continue;
               }
              if (deep && copy && (jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)))) {
                if (copyIsArray) {
                  // 重置数组判断标志
                  copyIsArray = false
                  clone = src && jQuery.isArray(src) ? src : []
                } else {
                  clone = src && jQuery.isPlainObject(src) ? src : {}
                }
                // 递归复制
                target[key] = jQuery.extend(deep, clone, copy)
              } else if (copy !== undefined && copy !== null) {
                // 浅复制
                target[key] = copy
              }
            }
          }
        }
        return target
      }
    
      // 共享原型对象
      jQuery.fn.init.prototype = jQuery.fn
    
      // jQuery 扩展
      jQuery.extend({
        isPlainObject: function (args) {
          return Object.prototype.toString.call(args) === "[object Object]"
        },
        isArray: function (args) {
          return toString.call(args) === "[object Array]"
        },
        isVoid: function (args) {
          return args === undefined || args === null || args === ''
        }
      })
    

    相关文章

      网友评论

          本文标题:jQuery 源码解析——无new构建实例和extend方法

          本文链接:https://www.haomeiwen.com/subject/yizacltx.html