JavaScript中的 深浅拷贝

阅读lazyload源代码时发现的这样一个函数,用于深浅拷贝对象的,觉得还不错就认真的了解了下,大致做了注释。

/**
 * @param {boolean} deep 是否需要深拷贝
 * @param {object} objects 拷贝的数组
 * @return {object} 拷贝后的对象
 */
const extend = function () {

    /**
     *  extended    拷贝后的对象
     *  deep        是否深拷贝
     *  i           记录 arguments 下标
     *  lenght      arguments长度
     */
    let extended = {},
        deep = false,
        i = 0,
        length = arguments.length;


    /**
     * 获取函数第一个参数
     * 判断是否需要深拷贝
     * 
     *                  Object.prototype.toString 方法返回一个表示该对象的字符串。
     *                 
     *                  Function.call(obj,params) 方法调用一个函数, 其具有一个指定的this值和参数的列表。
     * 
     */

    /**
     *  注 : 之所以使用 Object.prototype.toString 而不是 Object.toString 是为了防止 Object.toString 被复写
     *         下 prototype.hasOwnProperty 同
     */
    if (Object.prototype.toString.call(arguments[0]) === "[object Boolean]") {
        deep = arguments[0];
        i++;
    }


    /**
     * merge函数 合并对象到extended
     * @param {Object} obj 
     */
    let merge = function (obj) {
        for (let prop in obj) {

            /*
            * Object.prototype.hasOwnProperty(prop) 判断某个属性是否存在于对象,不返回存在于原型对象中的。
            *                               for in  循环会遍历对象的所有属性,包括原型中的。
            */ 
            if (Object.prototype.hasOwnProperty.call(obj, prop)) {

                //  如果是对象,即需要对引用进行深拷贝
                //  递归调用 extend
                if (deep && Object.prototype.toString.call(obj[prop]) === "[object Object]") {
                    extended[prop] = extend(true, extended[prop], obj[prop]);
                } else {
                // 基本数据类型 直接添加到extended对象 (boolean,string,null,undefined,number)
                    extended[prop] = obj[prop];
                }
            }
        }
    };

    // 遍历剩余参数
    // 拷贝所有的对象
    for (; i < length; i++) {
        let obj = arguments[i];
        merge(obj);
    }

    // 返回结果
    return extended;
};

你可能感兴趣的:(Javascript)