深度复制一个对象,看到很多种方法,最简单的是:
var newObject = JSON.parse(JSON.stringify(oldObject));
这样写有什么弊端吗?
学习是最好的投资!
oldObject = {a: 1, b: function() {}}
var newObject = Object.create(oldObject);
一般情况下通过 JSON 来复制挺好的,代码写起来也方便——不过并不是所有环境都实现了 JSON,这个需要考虑下。
JSON
通过 deep clone 一般都是有限定复制层次的,一般情况下不会无限层的复制下去。如果使用 JSON 方式来复制,通常不能控制层次。
深拷贝不就好了么。
https://github.com/XadillaX/nbut-online-judge-v2/blob/master/util/functions.js#L7-L28
/** * Deepin clone an object * @param obj * @returns {*} */ exports.cloneObject = function(obj) { if(typeof obj === "object") { if(util.isArray(obj)) { var newArr = []; for(var i = 0; i < obj.length; i++) newArr.push(obj[i]); return newArr; } else { var newObj = {}; for(var key in obj) { newObj[key] = this.cloneObject(obj[key]); } return newObj; } } else { return obj; } };
可以参考一下stackoverflow上关于克隆一个对象的有效方法
使用JSON接口有弊端,使用Object.create不会复制对象本身, 而是用对象的constructor重新构造一个对象。所以可以考虑使用Object.assign:
Object.create
Object.assign
let old_obj = [{a:1},{b:2}]; let new_obj = old_obj.map((ele)=>{ return Object.assign({},ele); }); old_obj[0].a=99; console.log(new_obj); // "[{a:1},{b:2}]"
这个看需求,我是搜索进来的,之前使用封装出来的深拷贝方法,结果不能满足我的需求,
建议如果数据格式大而且多样的话,最好是用楼主说的方法; 如果deepcopy的层级小的话,可以看下面的代码:
var hasOwn = Object.prototype.hasOwnProperty; function deepCopy(receiver, obj){ var args = [].slice.call(arguments), key, i = 1, deep, ride, value, valueType; if( typeof args[args.length-2] === "boolean" ){ deep = args.pop(); ride = args.pop(); }else{ ride = (typeof args[args.length-1] === "boolean")?args.pop():true; deep = false; if(args.length < 2){ receiver = ( this !== global ) ? this : {}; if( args.length === 0 ){ return receiver; } } } while( obj = args[ i++ ] ){ for( key in obj ){ if( hasOwn.call(obj, key) ){ if( ride || !(key in receiver) ){ value = obj[key]; valueType = type(value); if( deep && ( valueType==="object")){ receiver[key]={}; deepCopy(receiver[key], value, ride, deep); }else if( deep && ( valueType==="array" )){ receiver[key]=[]; deepCopy(receiver[key], value, ride, deep); }else{ receiver[key] = obj[key]; } } } } } return receiver; } // 类型判定对象 var class2type = { "[objectHTMLDocument]" : "document", "[objectHTMLCollection]" : "nodeList", "[objectStaticNodeList]" : "nodeList", "[objectIXMLDOMNodeList]" : "nodeList", "null" : "null", "NaN" : "NaN", "undefined" : "undefined" }; "Boolean, Number, String, Function, Array, Date, RegExp, Document, Arguments, NodeList" .replace( /[^, ]+/g, function( type ){ class2type["[object " + type + "]"] = type.toLowerCase(); } ); // 类型判定 function type( obj, isType ){ var key = ((obj == null || obj !== obj ) ? obj + "" : Object.prototype.toString.call( obj )), result; if( typeof(result = class2type[ key ]) !== "string" ){ if( obj.nodeType === 9 ){ result = class2type["Document"]; }else if( obj.item && typeof obj.length === "number" ){ result = class2type["NodeList"]; }else{ result = key.slice(8, -1); } } if( isType ){ return result === isType.toLowerCase; } return result; } export { deepCopy }; //根据开发模式选择使用或不使用,可取消
oldObject = {a: 1, b: function() {}}
一般情况下通过
JSON
来复制挺好的,代码写起来也方便——不过并不是所有环境都实现了JSON
,这个需要考虑下。通过 deep clone 一般都是有限定复制层次的,一般情况下不会无限层的复制下去。如果使用
JSON
方式来复制,通常不能控制层次。深拷贝不就好了么。
可以参考一下stackoverflow上关于克隆一个对象的有效方法
使用JSON接口有弊端,使用
Object.create
不会复制对象本身, 而是用对象的constructor重新构造一个对象。所以可以考虑使用
Object.assign
:这个看需求,我是搜索进来的,之前使用封装出来的深拷贝方法,结果不能满足我的需求,
建议如果数据格式大而且多样的话,最好是用楼主说的方法; 如果deepcopy的层级小的话,可以看下面的代码: