阅读 130

jQuery 源码分析 扩展插件

简介

  我们都知道jQuery的原型上有很多的方法, 那我们想给原型上继续添加方法的时候该怎么处理能,于是jQuery就额外提供了一个方法叫做extend方法来让大家公用,上节给大家讲了使用jQuery() 就相当于new jQuery.fn.init(),jQuery.fn.init又与init之间建立了联系,又把init的原型与jQuery.fn建立起来联系,jQuery.fn实际就是jQuery.prototype。我们extend方法就相当往jQuery.fn上添加方法。

extend 使用

  可以接收多个参数。假如只穿一个对象,那就是给jQuery 的原型上新添加方法了。 如果传入多个参数,会根据第一个参数来判断是是否是深拷贝。 使用arguments[0] ,根据arguments[0] 来判断,如果是基本类型如果是string、number等转成boolean类型,根据这个值来确定是否深拷贝。

使用$.extend与$.fn.extend的区别,$.fn是jquery的原型,$.extend是jquery的一个属性。使用上的区别也是有的。$.extend是jquery对象添加方法,使用$.fn.extend是给jquery原型上添加方法。

jQuery.extend = jQuery.fn.extend = function () {
    // 这里是对传入参数的一个处理
    var options, name, src, copy, copyIsArray,clone,
    // 拿到第一个传入的参数,如果没有值则赋值空对象
    target = arguments[0] || {},
    i = 1,
    length = arguments.length,
    deep = false;
    // target是true则要实现一个深拷贝
    // hanlde a deep copy situation 
    if (typeof target === 'boolean') {
        deep = target
        
        // 把target设置为目标值,如果arguments[1]存在值就使用arguments[1],否则设置为空对象
        target = arguments[i] || {}
        i++
    }
    // 如果target不是对象而不是函数,就给target一个初始值
    //jQuery target is a string or something (possible in deep copy)
    if (typeof target !== 'object' && !isFunction(target)) {
        target = {}
    }
    // 扩展jquery的target是一个字符串或者其他类型的值可能是深拷贝
    //Extend jQuery itself if only one argument is passed
    // 扩展jQuery自己本身如果只有一个参数
    if (i === length) {
        target = this
        i--
    }
    //上面是对两种情况的判断
    for(; i < length; i++) {
        //only deal with non-null/undefined values
        //如果第一个参数不是null
        if((options = arguments[i]) !== null) {
            // 扩展到target上
            for(name in options) {
                copy = options[name]
            }
            //如果是name是__proto__这个属性就直接跳进入下一轮循环
            if (name === '__proto__' || target === copy) {
                continue;
            }
            //递归如果我们合并纯对象或者数组
            if (deep && copy && jQuery.isPlainObject(copy) || (copyIsArray = Array.isArray(copy)))  {
                src = target [name]
                
                // 确保属性类型的值
                if (copyIsArray && !Array.isArray(src)) {
                    clone = []
                } else if (!copyIsArray && !jQuery.isPlainObject(src)) {
                    clone = {}
                } else {
                    clone = src
                }
                copyIsArray = false;
                
                // 不用以前的object, 克隆他们
                target[name] = jQuery.extend(deep, clone, copy)
            } else if (copy !== undefined) {
                target [name] = copy
            }
        
        }
        
    }
    return target
}
复制代码

使用方法

  • 单个参数
$.fn.extend({
   handleColor: function () {
       return this.each(function () {
            this.style.backgroundColor = 'red'
       })
   }
})
复制代码
  • 多个参数使用方法
    const a =  {a: 1}
    const c = { d: 3}
    const b =   {b: 2, c}

    const obj = $.extend(true, a, b)
    c.d = 6
    console.log(c) // {d: 6}
    console.log(b) //  {b: 2, c: { d: 6}}
    //可以看到这里已经把这个值已经给深度克隆了
    console.log(a) // {a: 1, b:2 ,c: {d :3}}
复制代码
文章分类
前端
文章标签