JQ第三部分源码学习

2019-07-19  本文已影响0人  没了提心吊胆的稗子

jQuery中的集成方法
$.extend()$.fn.extend
$.extend()是扩展插件的方法,作为工具方法,$或jQuery直接调用即可,一般用来完善类库
只写一个对象参数的时候
$.fn.extend() 是JQ作为一个类的时候,扩展原型上的方法,供JQ实例使用

$.extend({  // 扩展工具方法
    fn1: function() {
        console.log(1);
    },
    fn2: function() {
        console.log(2);
    }
});
// 调用
$.fn1();
$.fn2();
$.fn.extend({   // 扩展实例方法
    fn1: function() {
        console.log(1);
    },
    fn2: function() {
        console.log(2);
    }
})
// 调用
$('body').fn1();
$('body').fn2();

$.extend() -> this -> $ -> this.fn -> $.fn()
$.fn.extend() -> this -> $.fn -> this.fn -> $().fn()
写多个对象参数的时候,后面的都是扩展到第一个对象上面

var obj = {};
        $.extend(obj, { name: 'javascript' }, { age: 23 });
        console.log(obj);

extend实现深浅拷贝

// 效果跟Object.create()是一样的 浅拷贝
var a = {};
var c = {};
var b = {name: 'javascript', ary: [1,2,3]};
$.extend(a, b);
a.name = 'html';
console.log(b.name);  // javascript
a.ary[0] = 100;
console.log(b.ary);  // 100,2,3
// 深拷贝
$.extend(true, c, b);
c.ary[0] = 100;
console.log(b.ary);  // 1,2,3
// extend扩展到jQuery方法上 jQuery.fn是jQuery原型,实例方法
// $.extend() -> this -> $ -> this.fn -> $.fn()
// $.fn.extend() -> this -> $.fn  -> this.fn -> $().fn()
// 借助this可以用同样的方法实现
jQuery.extend = jQuery.fn.extend = function() {
    // 定义一些变量
    var options, name, src, copy, copyIsArray, clone,
        target = arguments[0] || {},
        i = 1,
        length = arguments.length,
        deep = false;

    // Handle a deep copy situation 判断是否是深拷贝的情况
    // $.extend(true, c, b) 若第一个是true的时候,目标元素下标就从1开始
    if ( typeof target === "boolean" ) {
        deep = target;
        target = arguments[1] || {};
        // skip the boolean and the target
        i = 2;
    }

    // 深拷贝情况下判断target的类型 参数是否正确
    // Handle case when target is a string or something (possible in deep copy)
    if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
        target = {};
    }

    // 判断是否是插件 即只有一个参数传进来 就是扩展插件的方法
    // extend jQuery itself if only one argument is passed
    // 此时的target就是当前this($和$.fn两种情况)
    if ( length === i ) {
        target = this;
        --i;
    }

    // 可能传入多个对象的情况,把后面的对象扩展到第一个上面
    for ( ; i < length; i++ ) {
        // Only deal with non-null/undefined values
        if ( (options = arguments[ i ]) != null ) {
            // Extend the base object
            for ( name in options ) {
                src = target[ name ];
                copy = options[ name ];

                // 防止循环引用 处理以下情况
                // var name = {}
                // $.extend(name, {name: name});
                // Prevent never-ending loop
                if ( target === copy ) {
                    continue;
                }

                // 深拷贝 判断要扩展的是不是对象或数组  拷贝继承(只能是对象或数组)
                // Recurse if we're merging plain objects or arrays
                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 : {};
                    }

                    // 利用递归 层层赋值
                    // Never move original objects, clone them
                    target[ name ] = jQuery.extend( deep, clone, copy );

                // 浅拷贝 就直接赋值
                // Don't bring in undefined values
                } else if ( copy !== undefined ) {
                    target[ name ] = copy;
                }
            }
        }
    }

    // Return the modified object
    return target;
};
上一篇下一篇

猜你喜欢

热点阅读