如何区分深拷贝与浅拷贝,简单来说,假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,如果B没变,那就是深拷贝;我们先看两个简单的案例:

//案例1(深拷贝)
var a1 = 1, a2= a1;
console.log(a1) //1
console.log(a2) //1
a2 = 2; //修改 a2
console.log(a1) //1
console.log(a2) //2
//案例2(浅拷贝)
var o1 = {x: 1, y: 2}, o2 = o1;
console.log(o1) //{x: 1, y: 2}
console.log(o2) //{x: 1, y: 2}
o2.x = 2; //修改o2.x
console.log(o1) //{x: 2, y: 2}
console.log(o2) //{x: 2, y: 2}

按照常规思维,o1应该和a1一样,不会因为另外一个值的改变而改变,而这里的o1 却随着o2的改变而改变了。同样是变量,为什么表现不一样呢?为了更好的理解js的深浅拷贝,我们先来理解一些js基本的概念 —— 目前JavaScript有五种基本数据类型(也就是简单数据类型),它们分别是:Undefined,Null,Boolean,Number和String。还含有一种复杂的数据类型(也叫引用类型),就是对象,引用类型有:Object、Array、Function(之所以说“目前”,因为之后也可能会有新的类型出来。)

一、基本类型和引用类型

ECMAScript变量可能包含两种不同数据类型的值:基本类型值和引用类型值。基本类型值指的是那些保存在栈内存中的简单数据段,即这种值完全保存在内存中的一个位置。而引用类型值是指那些保存堆内存中的对象,意思是变量中保存的实际上只是一个指针,这个指针指向内存中的另一个位置,该位置保存对象。

二、深拷贝与浅拷贝

既然已经知道了深拷贝与浅拷贝的来由,那么该如何实现深拷贝?我们先分别看看Array和Object自有方法是否支持:

1、Array

对于数组我们可以使用slice() 和 concat() 方法来解决上面的问题

1) slice

var arr1 = ['a', 'b'], arr2 = arr1.slice();
console.log(arr1); // ["a", "b"]
console.log(arr2); // ["a", "b"]
arr2[0] = 'c'; //修改arr2
console.log(arr1); // ["a", "b"]
console.log(arr2); // ["c", "b"]

此时,arr2的修改并没有影响到arr1,看来深拷贝的实现并没有那么难嘛。

2) concat

var arr1 = ['a', 'b'], arr2 = arr1. concat ();
console.log(arr1); // ["a", "b"]
console.log(arr2); // ["a", "b"]
arr2[0] = 'c'; //修改arr2
console.log(arr1); // ["a", "b"]
console.log(arr2); // ["c", "b"]

我们把arr1改成二维数组再来看看:

var arr1 = ['a', 'b', ['c', 'd']], arr2 = arr1.concat();
arr2[2][1] = 100;
console.log(arr1); //['a', 'b', ['c', 100]]
console.log(arr2); //['a', 'b', ['c', 100]]

咦,arr2又改变了arr1,看来slice()/concat()只能实现一维数组的深拷贝

除了上面两种方法外,我们还可以借用JQ的extend方法。

$.extend( [deep ], target, object1 [, objectN ] )

deep表示是否深拷贝,为true为深拷贝,为false,则为浅拷贝

target Object类型 目标对象,其他对象的成员属性将被附加到该对象上。

object1 objectN可选。 Object类型 第一个以及第N个被合并的对象。

var a=[0,1,[2,3],4],
b=$.extend(true,[],a);
a[0]=1;
a[2][0]=1; //
console.log(a); //[1,1,[1,3],4]
console.log(b); //[0,1,[2,3],4]

不过这种方法需要依赖JQ库。

2、Object

1) 利用对象的深拷贝实现原理

定义一个新的对象,遍历源对象的属性并赋给新对象的属性

var obj = {
  name:'sonia',
  age: 18
}
var obj2 = new Object();
obj2.name = obj.name;
obj2.age = obj.age;
obj.name = 'alice';
console.log(obj); //Object {name: "'alice'", age: 18}
console.log(obj2); //Object {name: "'sonia'", age: 18}

理解了以上的基本思想,我们就可以封装一个方法 deepCopy来实现对象的深拷贝,代码如下

var obj = {
  name: 'sonia',
  age: 18
}
var deepCopy = function (source) {
  var result = {};
  for(var key in source) {
  if(typeof source[key] === 'object') {
    result[key] = deepCopy(source[key])
  } else {
    result[key] = source[key]
  }
}
  return result;
}
var objCopy = deepCopy(obj) obj.name = 'aaa'; console.log(obj);//Object {name: "aaa", age: 18} console.log(objCopy);//Object {name: "sonia", age: 18}

2) JSON.parse(JSON.stringify(obj))

var obj = {
  name: 'sonia',
  age: 18
}
var obj2 = JSON.parse(JSON.stringify(obj));
obj.name = 'alice';
console.log(obj) // {name: "alice", age: 18}
console.log(obj2) // {name: "sonia", age: 18}

深入剖析javaScript中的深拷贝和浅拷贝的更多相关文章

  1. javascript中的深拷贝与浅拷贝

    javascript中的深拷贝与浅拷贝 基础概念 在了解深拷贝与浅拷贝的时候需要先了解一些基础知识 核心知识点之 堆与栈 栈(stack)为自动分配的内存空间,它由系统自动释放: 堆(heap)则是动 ...

  2. JavaScript中的深拷贝和浅拷贝!【有错误】还未修改!请逛其他园子!

    JavaScript中的深拷贝和浅拷贝! 浅拷贝 1.浅拷贝只是拷贝一层,更深层次对象级别的只拷贝引用.{也就是拷贝的是地址!简而言之就是在新的对象中修改深层次的值也会影响原来的对象!} // 2.深 ...

  3. Javascript中的深拷贝和浅拷贝

    var obj = { a:1, arr: [1,2] }; var obj1 = obj; //浅复制 var obj2 = deepCopy(obj); //深复制 javascript中创建对象 ...

  4. 理解JavaScript中的深拷贝和浅拷贝

    , num2 = num1;console.log(num1) //1console.log(num2) //1num2 = 2; //修改num2console.log(num1) //1conso ...

  5. 低门槛彻底理解JavaScript中的深拷贝和浅拷贝

    作者 | 吴胜斌 来源 | https://www.simbawu.com/article/search/9 在说深拷贝与浅拷贝前,我们先看两个简单的案例: //案例1var num1 = 1, nu ...

  6. 浅谈Java中的深拷贝和浅拷贝(转载)

    浅谈Java中的深拷贝和浅拷贝(转载) 原文链接: http://blog.csdn.net/tounaobun/article/details/8491392 假如说你想复制一个简单变量.很简单: ...

  7. C语言中的深拷贝和浅拷贝

    //C语言中的深拷贝和浅拷贝 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #inc ...

  8. 浅谈Java中的深拷贝和浅拷贝

    转载: 浅谈Java中的深拷贝和浅拷贝 假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(bool ...

  9. 内功心法 -- Java中的深拷贝和浅拷贝

    写在前面的话:读书破万卷,编码如有神--------------------------------------------------------------------这篇博客主要来谈谈" ...

随机推荐

  1. 微信 python搭建服务器

    1. 搭建服务以web.py网络框,python,腾讯云服务器为例介绍. 1)安装/更新需要用到的软件 安装python2.7版本以上 安装web.py pip install web.py sudo ...

  2. mysql中有多少种日志

    Mysql的日志包括如下几种日志: 错误日志 普通查询日志 二进制日志 慢查询日志 Mysql版本 此文档测试mysql的版本为 mysql -V 错误日志 error log Mysql错误日志主要 ...

  3. hbase-0.98.1-cdh5.1.0 完全分布式搭建

    cdh版与0.98版的配置一样 1.环境 master:c1 slave:c2,c3 CentOS 6.5 x64 ,hadoop-2.3.0-cdh5.1.0,zookeeper-3.4.5-cdh ...

  4. 12、IGV-Integrative Genomics Viewer

    1.IGV的网址:http://software.broadinstitute.org/software/igv/(java环境) 常见的几种输入格式bam/sam(比对文件)  TDF(bam的精简 ...

  5. sklearn解决过拟合的例子

    Learning curve 检视过拟合 sklearn.learning_curve 中的 learning curve 可以很直观的看出我们的 model 学习的进度, 对比发现有没有 overf ...

  6. sublime text 3如何安装插件和设置字号

    使用ctrl + ~(这个符号是键盘上1前面那个),如果不能调用出就需要修改快捷键,在Preferences ->Key Bindings - Default打开文件后,大概在248行,这里我修 ...

  7. Web应用之ActionForm

    看链接: 主要就是讲了一下form表单的传递,bean的工作原理. http://blog.csdn.net/java_pengjin/article/details/5987330

  8. Haproxy+Keepalived高可用配置

    基本实验 参考文档 博文地址 环境拓扑 下面使我们要实现的负载均衡集群图示 主节点地址: 92.0.0.11 从节点地址: 92.0.0.12 共享虚拟地址:92.0.0.8 下面是负载均衡集群可能出 ...

  9. 空字符串‘’ null false 区别

    1.''空字符串 .null 和false都是以值为0来存储的   只是数据结构不一致而已 空字符串------字符串数据格式 null -----------null数据格式 false ----- ...

  10. c# 衍生类和基类的构造顺序

    public class MyDeriveClass :MyBaseClass { public MyDeriveClass() :base() { } int derive_int = 1; } p ...