jquery.extend

jquery extend

實現extend 所須要的功能性函數html

// 判斷是否是函數
        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 代碼分析node

// 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;
    };
相關文章
相關標籤/搜索