$.extend中探索深拷贝和浅拷贝

来源:互联网 发布:2016义务兵退伍费算法 编辑:程序博客网 时间:2024/06/14 01:23

网上这方面的教程比较多,由于上次看了篇错误的教程搞得我迷糊;特意写下这篇笔记,若文中有错误之处,忘路过的朋友及时指出,不想祸害其他朋友了;

首先说明下:深拷贝(深复制)和浅拷贝(浅复制),特地说明怕有人以为又是不同的概念,其实是一样的;

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 ] || {},//获取第一个参数并赋给变量targeti = 1,length = arguments.length,//获取参数的长度deep = false;//deep变量决定是否进行普通拷贝还是递归拷贝// Handle a deep copy situationif ( typeof target === "boolean" ) { //判断变量target是否是boolean类型deep = target;// Skip the boolean and the targettarget = 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 ) {//并将参数复值给变量optionsfor ( name in options ) {src = target[ name ];copy = options[ name ];//判断目标对象和需要被复制的对象是否一致,一致就跳过进行下一次循环//目标对象target;被复制的对象copyif ( 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 themtarget[ name ] = jQuery.extend( deep, clone, copy );// Don't bring in undefined values} else if ( copy !== undefined ) {target[ name ] = copy;}}}}// Return the modified objectreturn target;};

从上面源码分析可知,jQuery中的extend()方法不过deep是否是true还是false,它都是进行深拷贝(深复制)的;同时extend方法进行深拷贝的条件还有需要被拷贝的对象,也就是extend()方法中的copy变量是否是对象还是数组;如果copy对象不是一个引用类型(对象或数组),比如字符串:则仍会将字符串作为类数组被for in进行循环并分解给目标对象target;并且不管是普通深拷贝还是递归深拷贝,最终返回的是被处理过的目标对象target;

代码如下: