浅谈Javascript中深复制

在javascript中,所有的object变量之间的赋值都是传地址的,可能有同学会问哪些是object对象。举例子来说明可能会比较好:

代码如下:

typeof(true)    //"boolean"
typeof(1)       //"number"
typeof("1")     //"string"
typeof({})      //"object"
typeof([])      //"object"
typeof(null)    //"object"
typeof(function(){})  //"function"

所以其实我们深复制主要需要处理的对象就是object对象,非object对象只要直接正常的赋值就好。我实现js深复制的思路就是:

遍历所有该对象的属性,
如果该属性是"object"则需要特殊处理,
如果这个object对象比较特殊,是一个数组,那就创建一个新的数组并深复制数组里的元素
如果这个object对象是个非数组对象,那直接再对它递归调用深复制方法即可。
如果不是"object",则直接正常复制就行。

下面就是我的实现了:

代码如下:

Object.prototype.DeepCopy = function () {
  var obj, i;
  obj = {};

for (attr in this) {
    if (this.hasOwnProperty(attr)) {
      if (typeof(this[attr]) === "object") {
        if (this[attr] === null) {
          obj[attr] = null;
        }
        else if (Object.prototype.toString.call(this[attr]) === '[object Array]') {
          obj[attr] = [];
          for (i=0; i<this[attr].length; i++) {
            obj[attr].push(this[attr][i].DeepCopy());
          }
        } else {
          obj[attr] = this[attr].DeepCopy();
        }
      } else {
        obj[attr] = this[attr];
      }
    }
  }
  return obj;
};

如果浏览器支持ECMAScript 5的话,为了深复制对象属性的所有特性,可以使用

代码如下:

Object.defineProperty(obj, attr, Object.getOwnPropertyDescriptor(this, attr));

来替代

代码如下:

obj[attr] = this[attr];

直接在Object.prototype上实现该方法的好处是,所有对象都会继承该方法。坏处是某些库也会改写Object对象,所以有时会发生冲突。这是需要注意的。具体使用方法如下:

代码如下:

Object.prototype.DeepCopy = function () { ... }
var a = { x:1 };
var b = a;
var c = a.DeepCopy();
a.x = 2;
b.x = 3;
console.log(a.x);   //3
console.log(b.x);   //3
console.log(c.x);   //1

以上就是关于深复制的讲解了,不过今天既然我们讲了深复制,那么想对应的还有浅复制,我们就来简单总结下他们之间的异同吧。

浅复制(影子克隆):只复制对象的基本类型,对象类型,仍属于原来的引用.
深复制(深度克隆):不紧复制对象的基本类,同时也复制原对象中的对象.就是说完全是新对象产生的.

(0)

相关推荐

  • Java中的深拷贝(深复制)和浅拷贝(浅复制)介绍

    深拷贝(深复制)和浅拷贝(浅复制)是两个比较通用的概念,尤其在C++语言中,若不弄懂,则会在delete的时候出问题,但是我们在这幸好用的是Java.虽然java自动管理对象的回收,但对于深拷贝(深复制)和浅拷贝(浅复制),我们还是要给予足够的重视,因为有时这两个概念往往会给我们带来不小的困惑. 浅拷贝是指拷贝对象时仅仅拷贝对象本身(包括对象中的基本变量),而不拷贝对象包含的引用指向的对象.深拷贝不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象.举例来说更加清楚:对象A1中包含对B1的引用

  • .NET的深复制方法(以C#语言为例)

    很多时候我们复制一个对象实例A到实例B,在用实例B去做其他事情的时候,会对实例B进行修改,为保证对B的修改不会影响到A的正常使用,就需要使用到深复制. 我在网上搜到一些深复制的方法,同时写了几组例子对这些方法进行测试. 我的操作系统版本为Win7旗舰版,.NET Framework版本是4.5 测试程序 我建了一个C#窗体应用程序(Winform),其主窗口FormMain的Load函数内容如下: private void FormMain_Load(object sender, EventAr

  • 改进版通过Json对象实现深复制的方法

    之前看到博客的关于Json对象的深复制方法,即 复制代码 代码如下: var obj = { sayName: function() { alert(this.name); }, name:'静水渊' };var cloneObj=JSON.parse(JSON.stringify(obj));cloneObj.sayName(); 但这种方式,不能复制属性值是函数的属性,因此改进了方法,以下是具体代码: 复制代码 代码如下: var obj = { sayName: function() {

  • 举例区分Python中的浅复制与深复制

    copy模块用于对象的拷贝操作.该模块非常简单,只提供了两个主要的方法: copy.copy 与 copy.deepcopy ,分别表示浅复制与深复制.什么是浅复制,什么是深复制,网上有一卡车一卡车的资料,这里不作详细介绍.复制操作只对复合对象有效.用简单的例子来分别介绍这两个方法. 浅复制只复制对象本身,没有复制该对象所引用的对象. #coding=gbk import copy l1 = [1, 2, [3, 4]] l2 = copy.copy(l1) print l1 print l2

  • Java中对象的深复制(深克隆)和浅复制(浅克隆)介绍

    1.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象. ⑵深复制(深克隆) 被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量.那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象.换言之,深复制把要复制的对象所引用的对象都复制了一遍. 2.Java的clone()方法 ⑴clone方法将对象复制了一份并返回

  • 理解java中的深复制和浅复制

    Java语言的一个优点就是取消了指针的概念,但也导致了许多程序员在编程中常常忽略了对象与引用的区别,本文会试图澄清这一概念.并且由于Java不能通过简单的赋值来解决对象复制的问题,在开发过程中,也常常要要应用clone()方法来复制对象.本文会让你了解什么是影子clone与深度clone,认识它们的区别.优点及缺点. 看到这个标题,是不是有点困惑:Java语言明确说明取消了指针,因为指针往往是在带来方便的同时也是导致代码不安全的根源,同时也会使程序的变得非常复杂难以理解,滥用指针写成的代码不亚于

  • javascript中的深复制详解及实例分析

     javascript中的深复制 JavaScript深拷贝是初学者甚至有经验的开发着,都会经常遇到问题,并不能很好的理解javascript的深拷贝.        深拷贝(deepClone)是神马,与深拷贝相对应的就是浅拷贝,刚开始我也没弄懂. 在很多情况下,我们都需要给变量赋值,给内存地址赋予一个值,但是在赋值引用值类型的时候,只是共享一个内存区域,导致赋值的时候,还跟之前的值保持一直性. 看一个具体的例子 // 给test赋值了一个对象 var test = { a: 'a', b:

  • 浅谈Javascript中深复制

    在javascript中,所有的object变量之间的赋值都是传地址的,可能有同学会问哪些是object对象.举例子来说明可能会比较好: 复制代码 代码如下: typeof(true)    //"boolean" typeof(1)       //"number" typeof("1")     //"string" typeof({})      //"object" typeof([])     

  • 浅谈JavaScript中面向对象的的深拷贝和浅拷贝

    理解深拷贝和浅拷贝之前需要弄懂一些基础概念,内存中存储的变量类型分为值类型和引用类型. 1.值类型赋值的存储特点, 将变量内的数据全部拷贝一份, 存储给新的变量. 例如:var num = 123 :var num1=num; 表示变量中存储的数字是 123.然后将数据拷贝一份,就是将 123 拷贝一份. 那么内存中有 2 个 数组;将拷贝数据赋值给 num2,其特点是在内存中有两个数据副本.这可以理解为浅拷贝. 2.引用类型的赋值. var o={name:'张三'}: var obj=o;

  • 浅谈JavaScript中数组的增删改查

    数组的增加 •ary.push()   向数组末尾添加元素,返回的是添加后新数组的长度,原有数组改变 •ary.unshift()  向数组开头添加元素,返回的是添加后新数组的长度,原有数组改变 • var ary=[1,2,3,4];   var res=ary.unshift(6);   console.log(res); ---->5 返回的是新数组的长度•ary.splice(n,m,x)从索引n开始删除m个元素,把新增的元素X放在索引n的前面,把删除的元素当成一个新数组返回,原有数组改

  • 浅谈javascript中的constructor

    constructor,构造函数,对这个名字,我们都不陌生,constructor始终指向创建当前对象的构造函数. 这里有一点需要注意的是,每个函数都有一个prototype属性,这个prototype的constructor指向这个函数,这个时候我们修改这个函数的prototype时,就发生了意外.如 function Person(name,age){ this.name = name; this.age = age; } Person.prototype.getAge = function

  • 浅谈javascript中的Function和Arguments

    javascript的Function 属性: 1.Arguments对象 2.caller 对调用单前函数的Function的引用,如果是顶层代码调用,  则返回null(firefox返回undefined).  注:只有在代码执行时才有意义 3.length 声明函数是指定的命名参数的个数(函数定义是,定义参数的个数) 4.prototype 一个对象,用于构造函数,这个对象定义的属性和方法  由构造函数创建的所有对象共享. 方法: applay() --> applay(this,[])

  • 浅谈javascript中new操作符的原理

    javascript中的new是一个语法糖,对于学过c++,java 和c#等面向对象语言的人来说,以为js里面是有类和对象的区别的,实现上js并没有类,一切皆对象,比java还来的彻底 new的过程实际上是创建一个新对象,把新象的原型设置为构造器函数的原型,在使用new的过程中,一共有3个对象参与了协作,构造器函数是第一个对象,原型对象是二个,新生成了一个空对象是第三个对象,最终返回的是一个空对象,但这个空对象不是真空的,而是已经含有原型的引用(__proto__) 步骤如下: (1) 创建一

  • 浅谈Javascript中的函数、this以及原型

    关于函数 在Javascript中函数实际上就是一个对象,具有引用类型的特征,所以你可以将函数直接传递给变量,这个变量将表示指向函数"对象"的指针,例如: function test(message){ alert(message); } var f = test; f('hello world'); 你也可以直接将函数申明赋值给变量: var f = function(message){ alert(message); }; f('hello world'); 在这种情况下,函数申明

  • 浅谈JavaScript中小数和大整数的精度丢失

    先来看两个问题: 0.1 + 0.2 == 0.3; // false 9999999999999999 == 10000000000000000; // true 第一个问题是小数的精度问题,在业界不少博客里已有讨论.第二个问题,去年公司有个系统的数据库在做数据订正时,发现有部分数据重复的诡异现象.本文将从规范出发,对上面的问题做个小结. 最大整数 JavaScript 中的数字是用 IEEE 754 双精度 64 位浮点数 来存储的,其格式为: s x m x 2^e s 是符号位,表示正负

  • 浅谈JavaScript中变量和函数声明的提升

    现象: 1. 在JavaScript中变量和函数的声明会提升到最顶部执行. 2. 函数的提升高于变量的提升. 3. 函数内部如果用var声明了相同名称的外部变量,函数将不再向上寻找. 4. 匿名函数不会提升. 5. 不同<script>块中的函数互不影响. 例子: 函数声明提升高于变量声明 //同时声明变量a和函数a var a; function a() {} alert(typeof a); //显示的是"function",初步证明function的优先级高于var.

  • 浅谈javascript中的加减时间

    上午在处理一些js中的日期参数的时候遇到了一点问题,不晓得如何加减时间. 最初的想法是自己分别取出year,month,day,hour,minute,second,然后手动加...开始想直接来个借位符就好了,后来一想,哪有那么容易. 最后,经过一个上午的摸索,终于搞定了. 首先是怎么显示一个标准的日期时间格式   "yyyy-mm-dd hh:MM:ss",暂时做法是先 var dtNow=new Date().//当前时间 标准的日期时间就拼出来,dtNow.getFullYear

随机推荐