JavaScript 中的对象深度复制(Object Deep Clone)

JavaScript中并没有直接提供对象复制(Object Clone)的方法。

JavaScript中的赋值,其实并不是复制对象,而是类似`c/c++`中的引用(或指针),因此下面的代码中改变对象b中的元素的时候,也就改变了对象a中的元素。

a = {k1:1, k2:2, k3:3};
b = a;
b.k2 = 4;

如果只想改变b而保持a不变,就需要对对象a进行复制。

用jQuery进行对象复制

在可以使用jQuery的情况下,jQuery自带的extend方法可以用来实现对象的复制。

a = {k1:1, k2:2, k3:3};
b = {};
$.extend(b,a);

自定义clone()方法来实现对象复制

1.下面的方法,是给Object的原型(prototype)添加深度复制方法(deep clone)。

 1 Object.prototype.clone = function() {
 2     // Handle null or undefined or function
 3     if (null == this || "object" != typeof this)
 4         return this;
 5     // Handle the 3 simple types, Number and String and Boolean
 6     if(this instanceof Number || this instanceof String || this instanceof Boolean)
 7         return this.valueOf();
 8     // Handle Date
 9     if (this instanceof Date) {
10         var copy = new Date();
11         copy.setTime(this.getTime());
12         return copy;
13     }
14     // Handle Array or Object
15     if (this instanceof Object || this instanceof Array) {
16         var copy = (this instanceof Array)?[]:{};
17         for (var attr in this) {
18             if (this.hasOwnProperty(attr))
19                 copy[attr] = this[attr]?this[attr].clone():this[attr];
20         }
21         return copy;
22     }
23     throw new Error("Unable to clone obj! Its type isn‘t supported.");
24 }

所有对象可以直接使用`.clone()`

var a=[1,2,true,null,"fdsfdsa",[1,"fdsa",{"a":1,"b":["fd",3,{"b":"3","c":""},new Date()],"c":new Date(),"d":false,"e":null}]];
var b=a.clone();

2.使用额外的工具函数实现,适用于大部分对象的深度复制(Deep Clone)。

 1 function clone(obj) {
 2     // Handle the 3 simple types, and null or undefined or function
 3     if (null == obj || "object" != typeof obj) return obj;
 4
 5     // Handle Date
 6     if (obj instanceof Date) {
 7         var copy = new Date();
 8         copy.setTime(obj.getTime());
 9         return copy;
10     }
11     // Handle Array or Object
12     if (obj instanceof Array | obj instanceof Object) {
13         var copy = (obj instanceof Array)?[]:{};
14         for (var attr in obj) {
15             if (obj.hasOwnProperty(attr))
16               copy[attr] = clone(obj[attr]);
17         }
18         return copy;
19     }
20     throw new Error("Unable to clone obj! Its type isn‘t supported.");
21 }

用法类似:

var a=[1,2,true,null,"fdsfdsa",[1,"fdsa",{"a":1,"b":["fd",3,{"b":"3","c":""},new Date()],"c":new Date(),"d":false,"e":null}]];
var b=clone(a);

测试

用上面两种方法都可以得到同样的结果。
至于用哪个怎么用,取决于你的喜好/习惯了 :)     就本人来说,我更倾向于使用原型的方法啦,方便嘛,啊哈哈哈~
你想测试结果的话,直接复制代码运行:

 1 var a=[1,2,true,null,"fdsfdsa",[1,"fdsa",{"a":1,"b":["fd",3,undefined,{"b":"3","c":""},new Date()],"c":new Date(),"d":false,"e":null,"f":function(){return 2;}}],function(){}];
 2 console.log("a=",a);
 3 console.log("b=a.clone();");
 4 b=a.clone();
 5 console.log("JSON.stringify(a)==JSON.stringify(b) = ",JSON.stringify(a)==JSON.stringify(b));
 6 console.log("JSON.stringify(a)===JSON.stringify(b) = ",JSON.stringify(a)===JSON.stringify(b));
 7 console.log("JSON.stringify(a) = ",JSON.stringify(a));
 8 console.log("JSON.stringify(b) = ",JSON.stringify(b));
 9 console.log("a[2]=123,b[2]=55555");
10 a[2]=123,b[2]=55555;
11 console.log("a=",a,"\t\t","b=",b);
12
13 console.log("b=clone(a);");
14 b=clone(a);
15 console.log("JSON.stringify(a)==JSON.stringify(b) = ",JSON.stringify(a)==JSON.stringify(b));
16 console.log("JSON.stringify(a)===JSON.stringify(b) = ",JSON.stringify(a)===JSON.stringify(b));
17 console.log("JSON.stringify(a) = ",JSON.stringify(a));
18 console.log("JSON.stringify(b) = ",JSON.stringify(b));
19 console.log("a[2]=1234,b[2]=33333");
20 a[2]=1234,b[2]=33333;
21 console.log("a=",a,"\t\t","b=",b);

可以看到, 输出结果 `a` 和 `b` 是相等的,但是 改变 `a` 的元素的值, 并不会影响到 `b` 的元素。

时间: 2024-10-22 06:20:29

JavaScript 中的对象深度复制(Object Deep Clone)的相关文章

深入探讨JavaScript如何实现深度复制(deep clone)

在代码复用模式里面有一种叫做“复制属性模式”(copying properties pattern).谈到代码复用的时候,很有可能想到的是代码的继承性(inheritance),但重要的是要记住其最终目标——我们要复用代码.继承性只是实现代码复用的一种手段,而不是唯一的方法.复制属性也是一种复用模式,它跟继承性是有所不同的.这种模式中,对象将从另外一个在对象中获取成员,其方法是仅需将其复制即可.用过jQuery的都知道,它有一个$.extend()方法,它的用途除了扩展第三方插件之外,还可以用来

【转】JavaScript中的对象复制(Object Clone)

JavaScript中并没有直接提供对象复制(Object Clone)的方法.因此下面的代码中改变对象b的时候,也就改变了对象a. a = {k1:1, k2:2, k3:3}; b = a; b.k2 = 4; 如果只想改变b而保持a不变,就需要对对象a进行复制. 用jQuery进行对象复制 在可以使用jQuery的情况下,jQuery自带的extend方法可以用来实现对象的复制. a = {k1:1, k2:2, k3:3}; b = {}; $.extend(b,a); 自定义clone

jQuery中json对象的复制(数组及对象)

摘自: http://www.2cto.com/kf/201306/218838.html 1.jQuery自带的$.map方式: $.map(json, function (n) { return n; }); 这种方式原来用于复制数组还可以,今天用它复制数组中的某一条记录,发现字段名称丢失了,后来发现了第二种方法. 2.深复制与浅复制 // 浅层复制(只复制顶层的非 object 元素) var newObject = jQuery.extend({}, oldObject); // 深层复

JavaScript中的对象

JavaScript对象 JavaScript对象是基本数据类型之一,是复合型数据: JavaScript中几乎所有事物都是做对象: JavaScript的对象是拥有属性和方法的数据: JavaScript 中的对象可以简单理解成"名称:值"对(name:value). JavaScript中的对象分类 1.内建对象: 数据分装对象(object.object.prototype.Number.Boolean.String.Array.Function): 工具类对象(Math.Dat

(转)JavaScript中判断对象类型的种种方法

我们知道,JavaScript中检测对象类型的运算符有:typeof.instanceof,还有对象的constructor属性: 1) typeof 运算符 typeof 是一元运算符,返回结果是一个说明运算数类型的字符串.如:"number","string","boolean","object","function","undefined"(可用于判断变量是否存在). 但 type

Javascript 中判断对象为空

发现了一个巧妙的实现: 需要检查一个对象(Object)是否为空,即不包含任何元素.Javascript 中的对象就是一个字典,其中包含了一系列的键值对(Key Value Pair).检查一个对象是否为空,等价于检查对象中有没有键值对.写成代码,形如: if (isEmptyObject(obj)) { // obj is empty } else { // not empty } 至于 isEmptyObject 的实现,jQuery 中有一个很有想法的方式,请看代码: function i

【好文收藏】javascript中event对象详解

event代表事件的状态,例如触发event对象的元素.鼠标的位置及状态.按下的键等等. event对象只在事件发生的过程中才有效. event的某些属性只对特定的事件有意义.比如,fromElement 和 toElement 属性只对 onmouseover 和 onmouseout 事件有意义. 例子 下面的例子检查鼠标是否在链接上单击,并且,如果shift键被按下,就取消链接的跳转. <HTML> <HEAD><TITLE>Cancels Links</T

javascript中event对象详解

event代表事件的状态,例如触发event对象的元素.鼠标的位置及状态.按下的键等等. event对象只在事件发生的过程中才有效. event的某些属性只对特定的事件有意义.比如,fromElement 和 toElement 属性只对 onmouseover 和 onmouseout 事件有意义. 例子 下面的例子检查鼠标是否在链接上单击,并且,如果shift键被按下,就取消链接的跳转. 前端UI资源I分享 <HTML> <HEAD><TITLE>Cancels L

JavaScript中的对象描述符(属性特性)

我们先创建一个对象: var person = { name: "Nicholas", _job: "Software Engineer", sayName: function(){ alert(this.name); }, get job(){ return this._job; }, set job(newJob){ this._job=newJob; } } 在这个对象中,我们定义了一个name属性和一个_job属性:至于以set和get开头的两处代码,他们共