网上这方面的教程比较多,由于上次看了篇错误的教程搞得我迷糊;特意写下这篇笔记,若文中有错误之处,忘路过的朋友及时指出,不想祸害其他朋友了;
首先说明下:深拷贝(深复制)和浅拷贝(浅复制),特地说明怕有人以为又是不同的概念,其实是一样的;
1.浅拷贝(浅复制):一句话概况就是多个对象之间对Objectl类型数据的备份,其实只是备份存储在栈内存中的地址;本质上还是指向同一个堆内存中的数据;
实例代码如下:
以上代码可知:当你改变obj对象的name属性,通过浅拷贝过去的obj1对象的name属性也会相应的改变;这种结果在跟后台做交互的时候会很出现各种各样的毛病;
2.深拷贝(深复制):深拷贝不再局限于对于对象内存地址的引用了,它是完全复制了一个对象,把被复制的对象的遍历一遍,然后赋值给新的对象并返回;
3.在jQuery框架中的$.extend()方法就是这么实现的;不过jQuery的深拷贝还分为两部分:普通深拷贝和递归(深度)深拷贝(我乱起的名字,不喜勿喷);我们就根据$.extend()方法来分析深拷贝;
先贴上jQuery源码:(只有$.extend方法的那一段)=>$.extend(boolean,obj1,obj2);
jQuery.extend = jQuery.fn.extend = function() {
var options, name, src, copy, copyIsArray, clone,
target = arguments[ 0 ] || {}, //获取第一个参数并赋给变量target
i = 1,
length = arguments.length, //获取参数的长度
deep = false; //deep变量决定是否进行普通拷贝还是递归拷贝
// Handle a deep copy situation
if ( typeof target === "boolean" ) { //判断变量target是否是boolean类型
deep = target;
// Skip the boolean and the target
target = arguments[ i ] || {};
i++;
}
// Handle case when target is a string or something (possible in deep copy)
if ( typeof target !== "object" && !jQuery.isFunction( target ) ) {
target = {};
}
//如果函数参数只有一个,那么target变量则引用jQuery实例化的对象;
if ( i === length ) {
target = this;
i--;
}
for ( ; i < length; i++ ) {//遍历所传参
if ( ( options = arguments[ i ] ) != null ) {//并将参数复值给变量options
for ( name in options ) {
src = target[ name ];
copy = options[ name ];
//判断目标对象和需要被复制的对象是否一致,一致就跳过进行下一次循环
//目标对象target;被复制的对象copy
if ( target === copy ) {
continue;
}
// 如果deep是true,copy是对象或者是数组则进行递归(也就是在函数里面调用自身)
//说明这里只是根据被复制的对象来决定是否进行递归,否则直接覆盖,不进行深度深拷贝
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;
};
从上面源码分析可知,jQuery中的extend()方法不过deep是否是true还是false,它都是进行深拷贝(深复制)的;同时extend方法进行深拷贝的条件还有需要被拷贝的对象,也就是extend()方法中的copy变量是否是对象还是数组;如果copy对象不是一个引用类型(对象或数组),比如字符串:则仍会将字符串作为类数组被for in进行循环并分解给目标对象target;并且不管是普通深拷贝还是递归深拷贝,最终返回的是被处理过的目标对象target;
代码如下: