js 中的深拷贝和浅拷贝

 Shallow copy && Deep copy

对于字符串类型,浅复制是对值的复制,对于对象来说,浅复制是对对象地址的复制,并没 有开辟新的栈,也就是复制的结果是两个对象指向同一个地址,修改其中一个对象的属性,则另一个对象的属性也会改变,

举个栗子

var arr = [1,2,3];
var arrCopy = arr;
arrCopy[0] = 100;   // 修改新数组的第0个值;
arr[0]===arrCopy[0];  //true  原来的数组四不四也变了 

而很多数情况下我们需要的是 新得到的对象与原来的对象互不相干,于是乎:

 深复制则是开辟新的栈,两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性。我们来看看以下方法。

Array 的 slice 和 concat 方法

//slice
var a = [1,2,3];
var b = a.slice();
b === a; // false

//concat
var a = [1,2,3];
var b = a.concat();
b === a;  // false

你可能会说你看他们没有指向同一个地址啊,喵的肯定是 deep copy,表捉急。请看下面:

var a = [[1,2,3],4,5];
var b = a.slice();
a[0][0]===b[0][0]; // true 

true 了我去,第二层的复制明显不是 deep copy 啊。

jQuery ——  $.extend()

我们可以通过 $.extend() 方法来完成  深浅复制。这个方法可以传入一个参数:deep(true or false),表示是否执行深复制(如果是深复制则会执行递归复制)。

var x = {
    a: 1,
    b: 2,
    c: {f:{g:1}}
};

var y = $.extend({}, x),          //浅 copy
    z = $.extend(true, {}, x);    //深 copy

y.c.f === x.c.f       // true
z.c.f === x.c.f       // false    $.extend 的用法很有意思,不单单只是 深浅copy, 有兴趣的崽儿可以到这个同学这里看看,总结的挺好https://segmentfault.com/a/1190000004082170

借助 JSON 全局对象

针对纯 JSON 数据对象的深复制,使用 JSON 全局对象的 parse 和 stringify 方法来实现深复制也算是一个简单讨巧的方法。

JOSN 对象中的 stringify 可以把一个 js 对象序列化为一个 JSON 字符串,parse 可以把 JSON 字符串反序列化为一个 js 对象,这两个方法实现的是深拷贝。然而使用这种方法会有一些隐藏的坑,

它能正确处理的对象只有 Number, String, Boolean, Array, 扁平对象(function 就歇菜了,原型链也没了),即那些能够被 json 直接表示的数据结构。



var arr = [0,1,2];
var arrCopy =  JSON.parse(JSON.stringify(arr));
arrCopy[0] = 333;
arr[0]===arrCopy[0];  // false

did u see that, 互不干扰,和谐盛世。

总结下:

Array 的 slice 和 concat 方法 和 jQuery 中的 extend 复制方法,他们都会复制第一层的值,对于 第一层 的值都是 深拷贝,

而到 第二层 的时候 Array 的 slice 和 concat 方法就是 复制引用 ,jQuery 中的 extend 复制方法 则 取决于 你的 第一个参数, 也就是是否进行递归复制。

而  JSON.parse(JSON.stringify(arr)) 在排除 被复制对象的 function 和原型链 之外,就是完全的复制啦 。

今天,就酱紫。88了。

时间: 2024-12-13 07:52:11

js 中的深拷贝和浅拷贝的相关文章

浅谈js中的深拷贝和浅拷贝

1. 如果是基本数据类型(String,Number,Boolean,Null,undefined),名字和值都会储存在栈内存中.栈内存中的数据每一次赋值都会产生一个新的内存,每条数据之间不相互影响, var a = 1; b = a; // 栈内存会开辟一个新的内存空间,此时b和a都是相互独立的 b = 2; console.log(a); // 1 2. 如果是引用数据类型(Object),名字存在栈内存中,值存在堆内存中,但是栈内存会提供一个引用的地址指向堆内存中的值. 例如:var a=

js中的深拷贝和浅拷贝

深复制和浅复制只针对像 Object, Array 这样的复杂对象的.简单来说,浅复制只复制一层对象的属性,而深复制则递归复制了所有层级. 深浅拷贝 的主要区别就是:复制的是引用(地址)还是复制的是实例. 所谓 深浅拷贝: 对于仅仅是复制了引用(地址),换句话说,复制了之后,原来的变量和新的变量指向同一个东西,彼此之间的操作会互相影响,为 浅拷贝. 而如果是在堆中重新分配内存,拥有不同的地址,但是值是一样的,复制后的对象与原来的对象是完全隔离,互不影响,为 深拷贝. 下面是一个简单的浅复制实现:

js 中的 深拷贝与浅拷贝

js在平时的项目中,赋值操作是最多的:比如说: 1 var person1 = { 2 name:"张三", 3 age:18, 4 sex:"male", 5 height:180, 6 weight:14012 } 13 var person2 = person1; 14 console.log(person2) 15 person2.name = "李四"; 16 console.log(person1,person2); 这段代码,con

js中的深拷贝与浅拷贝

对于字符串类型,浅拷贝是对值的拷贝,对于对象来说,浅拷贝是对对象地址的拷贝,并没有开辟新的栈,也就是拷贝的结果是两个对象指向同一个地址,修改其中一个对象的属性,则另一个对象的属性也会改变,而深拷贝则是开辟新的栈,两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性. 深拷贝的实现方法: b = JSON.parse( JSON.stringify(a) ) 这样做的局限性: 无法复制函数 原型链没了,对象就是object,所属的类没了. 另: jquery.extend()也

Java中的深拷贝和浅拷贝 原型模式

1: Java中浅拷贝和深拷贝的定义:      浅拷贝:就是指两个对象共同拥有同一个值,一个对象改变了该值,也会影响到另一个对象.      深拷贝:就是两个对象的值相等,但是互相独立. (深拷贝才是真正的拷贝,浅拷贝只是将引用指向了同一份对象) 2:Java中几种常见的拷贝操作: (1)"="操作:也就是赋值操作: (2)拷贝构造函数:拷贝构造函数就是构造函数的参数的类型是该构造函数所在的类,即参数就是该类的一个对象. <span style="font-size:

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

浅谈Java中的深拷贝和浅拷贝(转载) 原文链接: http://blog.csdn.net/tounaobun/article/details/8491392 假如说你想复制一个简单变量.很简单: [java] view plaincopyprint? int apples = 5; int pears = apples; int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(boolean,char,byte,short,float

**Python中的深拷贝和浅拷贝详解

Python中的深拷贝和浅拷贝详解 这篇文章主要介绍了Python中的深拷贝和浅拷贝详解,本文讲解了变量-对象-引用.可变对象-不可变对象.拷贝等内容. 要说清楚Python中的深浅拷贝,需要搞清楚下面一系列概念: 变量-引用-对象(可变对象,不可变对象)-切片-拷贝(浅拷贝,深拷贝) [变量-对象-引用] 在Python中一切都是对象,比如说:3, 3.14, 'Hello', [1,2,3,4],{'a':1}...... 甚至连type其本身都是对象,type对象 Python中变量与C/

python中的深拷贝和浅拷贝

1.深拷贝VS浅拷贝 python中的深拷贝和浅拷贝和java里面的概念是一样的, 所谓浅拷贝就是对引用的拷贝 (里面的数据不拷贝出来,其中的数据与原对象里面数据用的是相同的地址空间) 所谓深拷贝就是对对象的资源的拷贝 (里面的数据拷贝出来.深拷贝有自己的存储空间,有自己定义的数据,跟原对象一点关系也没有) 2.对赋值的认识: 赋值:将一个对象的地址赋值给一个变量,让变量指向该地址( 旧瓶装旧酒 ) 修改不可变对象(str.tuple)需要开辟新的空间 修改可变对象(list等)不需要开辟新的空

深入剖析javaScript中的深拷贝和浅拷贝

在面试时经常会碰到面试官问:什么是深拷贝和浅拷贝,请举例说明?如何区分深拷贝与浅拷贝,简单来说,假设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(浅拷