浅析javaScript中的浅拷贝和深拷贝(2)

这种方法使用较为简单,可以满足基本的深拷贝需求,而且能够处理JSON格式能表示的所有数据类型,但是对于正则表达式类型、函数类型等无法进行深拷贝(而且会直接丢失相应的值)。还有一点不好的地方是它会抛弃对象的constructor。也就是深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成Object。同时如果对象中存在循环引用的情况也无法正确处理。

4、jQuery.extend()方法源码实现

jQuery的源码 - src/core.js #L121源码及分析如下:

jQuery.extend = jQuery.fn.extend = function() { //给jQuery对象和jQuery原型对象都添加了extend扩展方法 var options, name, src, copy, copyIsArray, clone, target = arguments[0] || {}, i = 1, length = arguments.length, deep = false; //以上其中的变量:options是一个缓存变量,用来缓存arguments[i],name是用来接收将要被扩展对象的key,src改变之前target对象上每个key对应的value。 //copy传入对象上每个key对应的value,copyIsArray判定copy是否为一个数组,clone深拷贝中用来临时存对象或数组的src。 // 处理深拷贝的情况 if ( typeof target === "boolean" ) { deep = target; target = arguments[1] || {}; //跳过布尔值和目标 i++; } // 控制当target不是object或者function的情况 if ( typeof target !== "object" && !jQuery.isFunction(target) ) { target = {}; } // 当参数列表长度等于i的时候,扩展jQuery对象自身。 if ( length === i ) { target = this; --i; } for ( ; i < length; i++ ) { if ( (options = arguments[ i ]) != null ) { // 扩展基础对象 for ( name in options ) { src = target[ name ]; copy = options[ name ]; // 防止永无止境的循环,这里举个例子,如var i = {};i.a = i;$.extend(true,{},i);如果没有这个判断变成死循环了 if ( target === copy ) { continue; } if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { if ( copyIsArray ) { copyIsArray = false; clone = src && jQuery.isArray(src) ? src : [];// 如果src存在且是数组的话就让clone副本等于src否则等于空数组。 } else { clone = src && jQuery.isPlainObject(src) ? src : {};// 如果src存在且是对象的话就让clone副本等于src否则等于空数组。 } // 递归拷贝 target[ name ] = jQuery.extend( deep, clone, copy ); } else if ( copy !== undefined ) { target[ name ] = copy;// 若原对象存在name属性,则直接覆盖掉;若不存在,则创建新的属性。 } } } } // 返回修改的对象 return target; };

jQuery的extend方法使用基本的递归思路实现了浅拷贝和深拷贝,但是这个方法也无法处理源对象内部循环引用,例如:

var a={"name":"aaa"}; var b={"name":"bbb"}; a.child=b; b.parent=a; $.extend(true,{},a);//直接报了栈溢出。Uncaught RangeError: Maximum call stack size exceeded

5、自己动手实现一个拷贝方法

var $ = (function(){ var types = 'Array Object String Date RegExp Function Boolean Number Null Undefined'.split(' '); function type() { return Object.prototype.toString.call(this).slice(8, -1); } for (var i = types.length; i--;) { $['is' + types[i]] = (function (self) { return function (elem) { return type.call(elem) === self; }; })(types[i]); } return $; })();//类型判断 function copy(obj,deep){ if(obj === null || typeof obj !== "object"){ return obj; }       var name, target = $.isArray(obj) ? [] : {}, value; for(name in obj){ value = obj[name]; if(value === obj) { continue; } if(deep && ($.isArray(value) || $.isObject(value))){ target[name] = copy(value,deep); }else{ target[name] = value; } } return target; }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwgwzy.html