jQuery中extend()和fn.extend()方法详解

2020-05-22 17:07:11易采站长站整理

源对象不一定真的就是对像,也可以是其他类型的值比如字符串比如这样写:


console.log($.extend({‘name’:’tom’},’aa’));   //Object {0: “a”, 1: “a”, name: “tom”}

是不是感觉很奇怪啊?究竟是怎么实现的呢?下面接着看

过滤完之后开始进行for循环 src保存的是目标对象的某个键的值,copy属性保存的源对象的某个键的值,这两个键都是一样的


// Prevent never-ending loop
                if ( target === copy ) {
                    continue;
                }

如果源对象的某个属性值就是目标对象可能会造成死循环导致程序崩溃所以这里做了一个限制让其跳过此次循环例如:


var o = {};
o.n1 = o;
$.extend( true, o, { n2: o } );
// 抛出异常:
// Uncaught RangeError: Maximum call stack size exceeded

但是这样做也会冤枉一些正常的情况比如:


 var obj1={a:’a’}
 var obj2={a:obj1};
 console.log($.extend(obj1,obj2)); //Object {a: “a”}

这种情况也是满足源对象值等于目标对象的但是结果发现obj1的a的属性值并没有被修改,就是因为执行了continue,下面把源码的这段话注释掉在执行


Object {a: Object}

这个时候就是正常被修改了个人感觉这个地方需要改进;

接着就是一个if判断就是区分是不是进行深度复制的先不看深度复制的先看一般的


target[ name ] = copy;

很简单就是只要copy有值就直接复制给目标对象,目标对象有的就修改没有就增加,这样就实现了合并啦。

for循环之后在把新的目标对象返回,所以目标对象最后是被修改的,而且结果和返回的结果是一样的。


// Return the modified object
    return target;
};

下面再来说说深度复制了怎么去处理

首先保证deep是true,copy有值并且是对象或者数组(如果不是对象和数组深度复制也就无从谈起)然后再分数组和对象来处理,先来看数组的情况:


if ( copyIsArray ) {
         copyIsArray = false;
         clone = src && jQuery.isArray(src) ? src : [];

} else {
        clone = src && jQuery.isPlainObject(src) ? src : {};
}

如果是数组copyIsArray的值为真然后走里面的 把值改成false ,针对当前循环的源对象属性,目标对象可能有也可能没有,有的话判断一下是不是数组是的话就是原来的数组不变不是的话就让它变成一个数组,因为既然源对象的当前属性是数组最后目标元素也必须是数组。不是数组就是对象把目标对象当前属性改成对象。