jquery.extend

jquery extend

实现extend 所需要的功能性函数

        // 判断是不是函数
        function isFunction(obj) {
            // Support: Chrome <=57, Firefox <=52
            /* 
                在有些浏览器 typeof document.createElement( "object" ) 会返回function 
                所以判断是不是dom 节点
            */
            return typeof obj === "function" && typeof obj.nodeType !== "number";
        };
        // 创建一个计划对象
        let class2type = {};
        // 代理 hasOwnProperty 访问Object.hasOwnProperty的时候可以节省代码
        let hasOwn = class2type.hasOwnProperty;
        // hasOwn toString方法 注意是函数的toString方法,而不是{}toString 方法
        let fnToString = hasOwn.toString;
        // Object() 函数转成字符串 "function Object() { [native code] }"
        let ObjectFunctionString = fnToString.call(Object);
        // 代理
        let getProto = Object.getPrototypeOf;
        // 拷贝计划对象方法
        toString = class2type.toString;

        // 判断是否为计划对象
        /* 
            //在当前页面内追加换行标签和指定的HTML内容
            function w( html ){
                document.body.innerHTML += "<br/>" + html;
            }

            w( $.isPlainObject( { } ) ); // true
            w( $.isPlainObject( new Object() ) ); // true
            w( $.isPlainObject( { name: "CodePlayer"} ) ); // true
            w( $.isPlainObject( { sayHi: function(){} } ) ); // true
            w( $.isPlainObject( "CodePlayer" ) ); // false
            w( $.isPlainObject( true ) ); // false
            w( $.isPlainObject( 12 ) ); // false
            w( $.isPlainObject( [ ] ) ); // false
            w( $.isPlainObject( function(){ } ) ); // false
            w( $.isPlainObject( document.location ) ); // false(在IE中返回true)

            function Person(){
                this.name = "张三";
            }
            w( $.isPlainObject( new Person() ) ); // false
            window false
            new Date false
        */
        function isPlainObject(obj) {
            var proto, Ctor;
            // obj false,或者obj不是对象,排除null和undefined 否则getProto(obj) 报错
            if (!obj || toString.call(obj) !== "[object Object]") {
                return false;
            }
            proto = getProto(obj);
            // 如果是对象但是没有原型则是由 Object.create( null ) 创建
            if (!proto) {
                return true;
            }
            // 原型的构造函数是 Object(),则为计划对象
            Ctor = hasOwn.call(proto, "constructor") && proto.constructor;
            return typeof Ctor === "function" && fnToString.call(Ctor) === ObjectFunctionString;
        }

extend 代码分析

    // extend 代码分析
    var jQuery = {};
    /* 
        jQuery.extend()函数用于将一个或多个对象的内容合并到目标对象。
        jQuery.extend( [ deep ], target , object1 [, objectN... ] )
    */
    jQuery.extend = jQuery.prototype.extend = function () {
        // 定义后边用到的变量
        var options, name, src, copy, copyIsArray, clone,
            // 第一个参数为目标对象
            target = arguments[0] || {},
            i = 1,
            length = arguments.length,
            // 是否为深拷贝
            deep = false;

        // 深度拷贝
        /* 如果第一个参数为布尔值则代表深拷贝 */
        if (typeof target === "boolean") {
            deep = target;

            // Skip the boolean and the target 将第二个参数设置为目标对象
            target = arguments[i] || {};
            i++;
        }

        // 参数不是对象的情况
        if (typeof target !== "object" && !isFunction(target)) {
            target = {};
        }

        // 如果只有一个参数或者两个参数且第一个参数为 deep  扩展自身
        if (i === length) {
            target = this;
            i--;
        }

        for (; i < length; i++) {

            // 参数不是null 或者undefined
            /* 
                null == undefined // true
                null == null // true
            */
            if ((options = arguments[i]) != null) {

                // 扩展对象
                for (name in options) {
                    src = target[name];
                    copy = options[name];

                    /*
                        target = {a:1,b:2}
                        options = {
                            test: target
                        }
                        target.test = target; //会出现无法遍历
                    */
                    if (target === copy) {
                        continue;
                    }
                    // 判断是深拷贝,且copy为数组或者计划对象
                    /* 
                        计划对象
                        { } new Object()
                    */
                    if (deep && copy && (jQuery.isPlainObject(copy) ||
                        (copyIsArray = Array.isArray(copy)))) {
                        // 数组
                        if (copyIsArray) {
                            copyIsArray = false;
                            clone = src && Array.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 // 如果拷贝值为null/undefined 则不拷贝
                    } else if (copy !== undefined) {
                        target[name] = copy;
                    }
                }
            }
        }

        return target;
    };
    原文作者:wolfzwz
    原文地址: https://segmentfault.com/a/1190000017277488
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞