对象的深复制
- 源对象的属性更改,不会引起复制后的对象个属性的更改
- 源对象的任何属性与子属性与新对象的之间没有任何引用关系
代码bug正在修复:某些函数的函数名没有copy上,如n对象的value属性所代表的函数
测试用例:
var obj = { a: 1, b: "a", c: true, d: function (a, b) { if (a > 10) a = 10; if (b > 5) { b = 5; } else if (b < 0) { b = 0; } console.log(a + b); }, e: [1, 2, 3, 4], f: { g: ["a", "b", "c"], h: new Date(), i: /^[a-z]+$/g, j: { k: { }, l: [true, false], m: [ { id: 1001, name: "abc1" }, { id: 1002, name: "abc2" }, { id: 1003, name: "abc3" } ] } } } Object.defineProperties(obj.f.j, { n: { value: function () { console.log("abcd"); } }, o: { value: 10, enumerable: true }, p: { value: [1, 2, 3], writable: true }, q: { value: true, writable: true, enumerable: true } }); Object.defineProperties(obj.f.j.k, { r: { value: function () { }, writable: true }, s: { value: { a: 1 }, enumerable: true } }); // console.log(obj);
代码:
var obj1 = cloneObject(obj); obj.f.j.p[2]=10; console.log(obj,obj1); function cloneObject(sourceObj, targetObj) { // targetObj=targetObj || {}; if (!targetObj) { // sourceObj.constructor就是 sourceObj的类型 // sourceObj是数组 sourceObj.constructor->Array new Array(); targetObj=new sourceObj.constructor(); switch (sourceObj.constructor) { case RegExp: targetObj=new RegExp(sourceObj.source,sourceObj.flags); break; case Date: targetObj=new Date(sourceObj); break; } } var names = Object.getOwnPropertyNames(sourceObj); for (var i = 0; i < names.length; i++) { // console.log(names[i],sourceObj[names[i]]); // console.log(typeof sourceObj[names[i]]); var desc = Object.getOwnPropertyDescriptor(sourceObj, names[i]); if (typeof desc.value === "object") { var o = cloneObject(desc.value); Object.defineProperty(targetObj, names[i], { enumerable: desc.enumerable, configurable: desc.configurable, writable: desc.writable, value: o }); } else if (typeof desc.value === "function") { var fnStr = desc.value.toString().replace(/\n/g, ""); var arg = fnStr.match(/\((.*?)\)/)[1]; var content = fnStr.match(/{(.*)}/)[1]; var fn = new Function(arg, content); Object.defineProperty(targetObj, names[i], { enumerable: desc.enumerable, configurable: desc.configurable, writable: desc.writable, value: fn }); } else { Object.defineProperty(targetObj, names[i], desc); } } return targetObj; }