如何区分深拷贝与浅拷贝,简单来说,假设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. 使用GEO数据库来筛选差异表达基因,KOBAS进行KEGG注释分析

    前言 本文主要演示GEO数据库的一些工具,使用的数据是2015年在Nature Communications上发表的文章Regulation of autophagy and the ubiquiti ...

  2. 面试题18(一):在O(1)时间删除链表结点

    // 面试题18(一):在O(1)时间删除链表结点 // 题目:给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该 // 结点.链表结点与函数的定义如下: // struct Lis ...

  3. Linux的.run文件简单制作

    run程序安装包实质上是一个安装脚本加要安装的程序,如下图所示: |-----------------|| || 安装脚本 || ||-----------------|| || 程序 || ||-- ...

  4. python接口自动化(三十五)-封装与调用--流程类接口关联(详解)

    简介 流程相关的接口,主要用 session 关联,如果写成函数(如上篇),s 参数每个函数都要带,每个函数多个参数,这时候封装成类会更方便.在这里我们还是以博客园为例,带着小伙伴们实践一下. 接口封 ...

  5. 【leetcode 114. 二叉树展开为链表】解题报告

    思路:递归,将左子树变成单链表形式,再将右子树变成单链表形式,最后将左子树单链表的末端连接到右子树单链表表头,将根节点的左孩子置空 void flatten(TreeNode* root) { if ...

  6. yarn快速使用及实践建议

    什么是 yarn? 简单来说,yarn 是一个与 npm 功能相同的工具,用于前端项目的依赖管理.在使用 npm 的项目中,使用 npm 命令的地方都可以使用 yran 来代替. 为什么要使用 yar ...

  7. Web——页面“传值、赋值”与页间“传值”

    前言 前期我们学习C/S开发的时候,采用三层架构,U层的参数在每个层之间传来传去,那么现在我们接触到的B/S,在Web前端是如何与后台进行传值赋值呢?由于本人是菜鸟一枚,下面写的不恰当的地方,望路过的 ...

  8. Stream流、方法引用

    Stream流.方法引用 Stream流.方法引用 Stream流.方法引用 Stream流.方法引用 Stream流.方法引用 ... ...

  9. 虚拟机上安装Cell节点(12.1.2.3.3)

    安装介质下载 打开firefox,输入:https://edelivery.oracle.com 点击"Sign In",输入帐号.密码,登陆edelivery网站.       ...

  10. 响应式Web

    响应式布局的核心是:适配不同视口大小的流式布局. RWD和AWD RWD:Responsive Web Design AWD:Adaptive Web Design 实现RWD,多使用流式布局.针对所 ...