js中浅拷贝和深拷贝以及深拷贝的实现

前言:2019年的第一篇分享...

一、什么是基本类型值和引用类型值?
ECMAScript包括两个不同类型的值:基本数据类型和引用数据类型。
基本数据类型指的是简单的数据段,引用数据类型指的是有多个值构成的对象。
当我们把变量赋值给一个变量时,解析器首先要确认的就是这个值是基本类型值还是引用类型值。

注:要了解深拷贝和浅拷贝,首先要先理解ECMAScript中的数据类型,其中基本类型值(如undefined、null、number、string、boolean以及es6新增的Symbol), 还有一些引用类型值(如对象)。
  浅拷贝和深拷贝一般是对于引用类型值(如对象)来讲的,而基本类型值,只要是复制,就一定是另开辟以存储空间。

1 // 示例1(基本类型值))
2 var a = 10;
3 var b = a;
4 b = 20;
5 console.log(b); //输出 20
6 console.log(a); //输出 10

// 类似示例1,基本类型在拷贝的时候,b改变了,但是并不会印象到a。
1 // 示例2(引用类型值)
2 var obj_a = { a: 10, b: 20 };
3 var obj_b = obj_a;
4 obj_b.a = 30;
5 console.log(obj_b); //输出 { a: 30, b: 20 }
6 console.log(obj_a); //输出 { a: 30, b: 20 }
7
8 // 类似示例2,复杂类型在拷贝的时候,然后改变了obj_b的属性的值,但是却改变了obj_a的,很明显,这个结果并不是我们想要的,其实他们还是指向同一个对象,只是展示窗口的位置不同而已。
1 // 示例3(应用类值&深拷贝)
2 var obj_a = { a: 10, b: 20, c: 30 };
3 var obj_b = { a: obj_a.a, b: obj_a.b, c: obj_a.c };
4 obj_b.a = 40;
5 console.log(obj_b); //输出 { a: 40, b: 20, c: 30 }
6 console.log(obj_a); //输出 { a: 10, b: 20, c: 30 }
7
8 // 类似示例3,复杂类型在拷贝的时候,然后改变了obj_b的属性的值,但是却没有改变了obj_a的,因为在拷贝的时候,其实是相当于新建了一个领地,然后遍历旧对象的每一项的值,在新对象里面新建每一项,然后把对应的值复制进去,他们是不同的对象,这就是所谓的深拷贝。
二、浅拷贝和深拷贝的原理
1.基本数据类型值( 基本数据类型值的名和值都存在栈内存里面 )

如:let a = 1; 如图:

当let b = a,b复制了a,栈内存会另外开辟一块地方存放b的名值,如图:

两者互不干涉,谁也没有影响到谁。

2.引用数据类型值( 引用数据类型值栈内存里面存值的位置则存放的是a的值在堆内存里面的位置,也就是唯一堆地址 )
如:let a = [ 0, 1, 2, 3, 4 ];如图:

当let b = a,b复制了a,b引用了a的堆地址。如图:

所以这个时候,改变了b,a也会受到影响。
 
三、实现深拷贝
层级拷贝,递归方式(其实就是函数的自我调用)
何为层级?如,var a = [0,1,[3,4],3];
数组嵌套着数组。

 实现方法:

 // 代码中加入判断,当碰到数组、对象等时递归函数  1 function deepClone(obj){
 2         //定义对象来判断当前的参数是数组还是对象
 3         let objClone = Array.isArray(obj)?[]:{};
 4         //如果obj存在并且为对象
 5         if(obj&&typeof obj == "object"){
 6             for(let key in obj){
 7                 if(obj.hasOwnProperty(key)){
 8                     //如果obj的子元素为对象,那么递归(层级遍历)
 9                     if(obj[key]&&typeof obj[key] == "object"){
10                         objClone[key] = deepClone(obj[key]);
11                     }else{
12                     //如果不是,直接赋值
13                         objClone[key] = obj[key];
14                     }
15                 }
16             }
17         }
18         return objClone;
19     }

利用 jeury.extend() 浅拷贝&深拷贝

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

注:deep表示是否深拷贝,为true为深拷贝,为false,则为浅拷贝
  target Object类型 目标对象,其他对象的成员属性将被附加到该对象上。
  object1 objectN可选。 Object类型 第一个以及第N个被合并的对象。



1 let a = [0, 1, [2, 3], 4],
2    b = $.extend(true, [], a);
3 a[0] = 1;
4 a[2][0] = 1;
5 console.log(a, b);
通过ES6的 concat() 方法
concat()用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。


1 var a  = [1,2,3]
2 var b = a.concat();
3 b[2] =10;
4 console.log(a

上面这个情况a的值并没有改变。

以上就是我的一些个人的理解和靖藏使用的一些深拷贝的处理方法,仅供参考。

原文地址:https://www.cnblogs.com/it-xiong/p/10476940.html

时间: 2024-07-30 17:55:49

js中浅拷贝和深拷贝以及深拷贝的实现的相关文章

JS中如何进行对象的深拷贝

在JS中,一般的=号传递的都是对象/数组的引用,并没有真正地拷贝一个对象,那如何进行对象的深度拷贝呢?如果你对此也有疑问,这篇文章或许能够帮助到你 一.对象引用.浅层拷贝与深层拷贝的区别 js的对象引用传递理解起来很简单,参考如下代码: var a = {name:'wanger'} var b = a ; a===b // true b.name = 'zhangsan' a.name //'zhangan' 上述代码中,使用了=进行赋值,于是b指向了a所指向的栈的对象,也就是a与b指向了同一

JS中有关对象的继承以及实例化、浅拷贝深拷贝的奥秘

一.属性的归属问题 JS对象中定义的属性和方法如果不是挂在原型链上的方法和属性(直接通过如类似x的方式进行定义)都只是在该对象上,对原型链上的没有影响.对于所有实例共用的方法可直接定义在原型链上这样实例化的的时候就不用对每个实例定义该属性方法,所有的实例均具有该方的引用见最后的输出. function Myclass(){ this.x=" x in Myclass"; this.get=function(){}//每次实例化对象,每个对象的该方法都是独立的,是不相同的 } Mycla

JS中深拷贝与浅拷贝的区别,实现深拷贝的几种方法

JS中深拷贝与浅拷贝的区别,实现深拷贝的几种方法 如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力. 此篇文章中也会简单阐述到栈堆,基本数据类型与引用数据类型,因为这些概念能更好的让你理解深拷贝与浅拷贝. 我们来举个浅拷贝例子: let a=[0,1,2,3,4], b=a; console.log(a===b); a[0]=1; console.log(a,b); 嗯?明明b复

js中对象的浅拷贝和深拷贝的区别

js中对象的浅拷贝和深拷贝的区别 浅度拷贝:复制一层对象的属性,并不包括对象里面的为引用类型的数据,当改变拷贝的对象里面的引用类型时,源对象也会改变. 深度拷贝:重新开辟一个内存空间,需要递归拷贝对象里的引用,直到子属性都为基本类型.两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性. 数据的类型: 一般数据(值传递):字符,数值,布尔,undefined 拷贝(复制)时,传递的是值,修改新数据,不会影响老数据 复杂数据(引用传递):对象 拷贝(复制)时,传递的是内存地址的

JS中深拷贝和浅拷贝记录及解决方法

这是本人第一次写博客...好紧张,有什么固定格式麽,需要爆照麽..怎样才能让自己表现的不是第一次啊.. 不多说,最近一不小心就跳入一个坑,也是怪我自己知识点扩展不够..这次记录下,上代码 /*a 原来的数组* b 复制后的新数组* */function copy(a,b) { for(var i=0;i<a.length;i++) { b.push(a[i]) }}var arr1=[1,2,3,4,5];var arr2=[];copy(arr1,arr2);console.log(arr2)

浅谈JS中的浅拷贝与深拷贝

前端工程师应该都比较熟悉浅拷贝和深拷贝的概念,在日常业务代码的过程中,特别是做数据处理的时候,经常行的会遇到,比如如何在不修改原对象的基础上,重新生成一个一模一样的对象,加以利用,又或是,如何巧妙地运用相关的内置API,来达成自己所需要的结果,比如数组相关的操作,splice和slice就是截然相反的处理,虽然同样是对数组进行截取操作,但是前者会影响原数组,后者则是返回一个新的数组对象,而对原来的数组并不会产生任何影响,这其中的差别,需要有一定的开发经验才能明白. 好了,废话也不多说,下面来简单

js中对象的复制,浅复制(浅拷贝)和深复制(深拷贝)

在js中,我们经常复制一个对象,复制数据,那么就会有人问了,怎么复制,今天鹏哥就带来js中的复制方法. JS中对象分为基本类型和复合(引用)类型,基本类型存放在栈内存,复合(引用)类型存放在堆内存. 堆内存用于存放由new创建的对象,栈内存存放一些基本类型的变量和对象的引用变量. 至于堆内存和栈内存的区别介绍,你们可以百度看看. 下面开始讲解复制: 这种只是简单的变量,内存小,我们直接复制不会发生引用. var a=123; var b=a; a=123456; alert(a); //1234

js对象浅拷贝和深拷贝详解

js对象浅拷贝和深拷贝详解 作者:i10630226 字体:[增加 减小] 类型:转载 时间:2016-09-05我要评论 这篇文章主要为大家详细介绍了JavaScript对象的浅拷贝和深拷贝代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 本文为大家分享了JavaScript对象的浅拷贝和深拷贝代码,供大家参考,具体内容如下 1.浅拷贝 拷贝就是把父对像的属性,全部拷贝给子对象. 下面这个函数,就是在做拷贝: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 var

js的命名空间 &amp;&amp; 单体模式 &amp;&amp; 变量深拷贝和浅拷贝 &amp;&amp; 页面弹窗设计

说在前面:这是我近期开发或者看书遇到的一些点,觉得还是蛮重要的. 一.为你的 JavaScript 对象提供命名空间 <!DOCTYPE html> <html> <head> <title>为自己的js对象提供命名空间</title> </head> <body> <div>封装自己的数据和函数,防止和其他的库搞混了</div> <script> var jscbObject = {