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

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

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

 // 示例1(基本类型值))
var a = 10;
var b = a;
b = 20;
console.log(b); //输出 20
console.log(a); //输出 10 // 类似示例1,基本类型在拷贝的时候,b改变了,但是并不会印象到a。
 // 示例2(引用类型值)
var obj_a = { a: 10, b: 20 };
var obj_b = obj_a;
obj_b.a = 30;
console.log(obj_b); //输出 { a: 30, b: 20 }
console.log(obj_a); //输出 { a: 30, b: 20 } // 类似示例2,复杂类型在拷贝的时候,然后改变了obj_b的属性的值,但是却改变了obj_a的,很明显,这个结果并不是我们想要的,其实他们还是指向同一个对象,只是展示窗口的位置不同而已。
 // 示例3(应用类值&深拷贝)
var obj_a = { a: 10, b: 20, c: 30 };
var obj_b = { a: obj_a.a, b: obj_a.b, c: obj_a.c };
obj_b.a = 40;
console.log(obj_b); //输出 { a: 40, b: 20, c: 30 }
console.log(obj_a); //输出 { a: 10, b: 20, c: 30 } // 类似示例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){
//定义对象来判断当前的参数是数组还是对象
let objClone = Array.isArray(obj)?[]:{};
//如果obj存在并且为对象
if(obj&&typeof obj == "object"){
for(let key in obj){
if(obj.hasOwnProperty(key)){
//如果obj的子元素为对象,那么递归(层级遍历)
if(obj[key]&&typeof obj[key] == "object"){
objClone[key] = deepClone(obj[key]);
}else{
//如果不是,直接赋值
objClone[key] = obj[key];
}
}
}
}
return objClone;
}

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

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

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


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

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

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

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

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

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

    在JS中,一般的=号传递的都是对象/数组的引用,并没有真正地拷贝一个对象,那如何进行对象的深度拷贝呢?如果你对此也有疑问,这篇文章或许能够帮助到你 一.对象引用.浅层拷贝与深层拷贝的区别 js的对象引 ...

  2. js 中数组或者对象的深拷贝和浅拷贝

    浅拷贝 : 就是两个js 对象指向同一块内存地址,所以当obj1 ,obj2指向obj3的时候,一旦其中一个改变,其他的便会改变! 深拷贝:就是重新复制一块内存,这样就不会互相影响. 有些时候我们定义 ...

  3. js 中多维数组的深拷贝的多种实现方式

    因为javascript分原始类型与引用类型(与java.c#类似).Array是引用类型,所以直接用=号赋值的话,只是把源数组的地址(或叫指针)赋值给目的数组,并没有实现数组的数据的拷贝.另外对一维 ...

  4. JS中多维数组的深拷贝的多种实现方式

    因为javascript分原始类型与引用类型(与java.c#类似).Array是引用类型,所以直接用=号赋值的话,只是把源数组的地址(或叫指针)赋值给目的数组,并没有实现数组的数据的拷贝.另外对一维 ...

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

    一.属性的归属问题 JS对象中定义的属性和方法如果不是挂在原型链上的方法和属性(直接通过如类似x的方式进行定义)都只是在该对象上,对原型链上的没有影响.对于所有实例共用的方法可直接定义在原型链上这样实 ...

  6. js中的数据类型、以及浅拷贝和深拷贝

    一.js中的数据类型 1.基本类型(值类型):Undefined.Boolean.String.Number.Symbol 2.引用类型:函数.数组.对象.null.new Number(10)都是对 ...

  7. js中的extend,可实现浅拷贝深拷贝

    js中的extend   1.    JS中substring与substr的区别 之前在项目中用到substring方法,因为C#中也有字符串的截取方法Substring方法,当时也没有多想就误以为 ...

  8. js 中的深拷贝与浅拷贝

    在面试中经常会问到js的深拷贝和浅拷贝,也常常让我们手写,下面我们彻底搞懂js的深拷贝与浅拷贝. 在js中 Array 和 Object  这种引用类型的值,当把一个变量赋值给另一个变量时,这个值得副 ...

  9. 在js中如何区分深拷贝与浅拷贝?

    一.自我理解 简单来讲就是:深拷贝层层拷贝,浅拷贝只拷贝第一层. 在深拷贝中,新对象中的更改不会影响原对象,而在浅拷贝中,新对象中的更改,原对象中也会跟着改. 在深拷贝中,原对象与新对象不共享相同的属 ...

随机推荐

  1. linux 启动流程

    启动第一步--加载BIOS 当你打开计算机电源,计算机会首先加载BIOS信息,BIOS信息是如此的重要,以至于计算机必须在最开始就找到它.这是因为BIOS中包含了CPU的相关信息.设备启动顺序信息.硬 ...

  2. 2019.04.10打卡(HTML)

    代码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.o ...

  3. vector内存回收

    1. vector所有的内存相关问题都可以归结于它的内存增长策略.vector有一个特点就是:内存空间只会增长不会减少.vector有两个函数,一个是capacity(),返回对象缓冲区(vector ...

  4. Intellij IDEA 远程链接hive,执行hsql

    https://note.youdao.com/share/?id=75d82d9c5fab1e00de41c504a54dfcde&type=note#/

  5. oracle 锁表

    select b.username,b.sid,b.serial#,logon_time from v$locked_object a,v$session b where a.session_id = ...

  6. 使用代理实现对C# list distinct操作

    范型在c#编程中经常使用,而经常用list 去存放实体集,因此会设计到对list的各种操作,比较常见的有对list进行排序,查找,比较,去重复.而一般的如果要对list去重复如果使用linq dist ...

  7. Go 参数传递是传值还是传引用

    什么是传值(值传递)? 传值的意思是:函数传递的总是原来这个东西的一个副本.一个副拷贝.比如我们传递一个 int 类型的参数,传递 的其实这个参数的一个副本:传递一个指针类型的参数,其实传递的是这个指 ...

  8. Unity自定义定时器,模拟协程,脱离MonoBehavior控制

    using System; using System.Collections.Generic; using System.Timers; public class PETimer { private ...

  9. VirtualBox中CentOS7.2 网络配置(固定IP+联网)

    一.前言 用虚拟机装Linux系统时,经常会出现一些问题.比如:从主机到虚拟机之间网络不通:虚拟机中无法联网:虚拟机中的IP地址不固定.为了解决这些问题,我曾花了不少时间.在此,记下填坑方法. 二.环 ...

  10. @staticmethod和@classmethod

    一般来说,要使用某个类的方法,需要先实例化一个对象再调用方法. 而使用@staticmethod或@classmethod,就可以不需要实例化,直接类名.方法名()来调用. 这有利于组织代码,把某些应 ...