如何区分深拷贝与浅拷贝,简单来说,假设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. Servlet编程实例

    ---------------siwuxie095 登录实例: 从 login.jsp 提交登录信息到 LoginServlet,在 LoginServlet 中打印登录信息 工程结构目录如下: Lo ...

  2. SpringBoot02 Controller的使用、数据库操作、事物管理、修改banner

    1 Controller的使用 特点:编程技巧和SpringMVC几乎完全一样 注意:@RestController = @Controller + @ResponseBody 注意:读取路径参数和请 ...

  3. Ensembl突变数据描述之(一)——突变物种数据库及预测工具

    以下是对Ensembl突变数据库中储存的数据的描述,对于Ensembl数据库中不同的物种,我们从各种来源(例如,dbSNP数据库)导入突变数据(SNP.CNV.等位基因频率.基因型等),导入的突变数据 ...

  4. Asp.net Core 使用 EntityFrameworkCore 1.1

    前言 相比大家也在开发中是非常喜欢用ORM的.今天就来介绍一下EntityFrameworkCore的使用方法. 自从EF Core升级到1.1之后,确实变化挺大的.如果没试过真的不知道坑是挺多的.今 ...

  5. webAPI中使用log4net进行日志记录

    1.从nuget下载log4net 2.根据需求配置web.config,或者另外写一个log4net.config文件,各个节点的意义详细查询api <section name="l ...

  6. js复习笔记

    isNaN(x) 1.判断结果不是纯数字, var a=1234var b =isNan(a) //b是 false 因为a是纯数字 var a="abc123"var b =is ...

  7. 【mysql-索引+存储过程+函数+触发器-更新。。。】

    BaseOn ===>MySQL5.6 一:索引 1:创建索引: create index nameIndex on seckill(name) ; 2:查看索引: show index fro ...

  8. 数组API(2)

    ES5中数组新增API: 1. indexOf 作用:检测当前数据是否在数组中存在: 特点:如果存在返回相对应的下标,如果不存在则返回-1: 如果数组中存在多个需要判断的这个数据,则返回最近的这个数据 ...

  9. 将图片至于jsp页面上(层)

    <div style="position: relative"> <span style="position: relative; top: 1px; ...

  10. Spring AOP 自定义注解实现统一日志管理

    一.AOP的基本概念: AOP,面向切面编程,常用于日志,事务,权限等业务处理.AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容(Spring核心之一),是函数式编程 ...