js深拷贝你还不会吗
js深拷贝
在讲正题之前我们要先了解数据存储的方式
数据存储方式
在讲之前我们要先知道值类型和引用类型的存储方式。
在JavaScript数据类型中有两种数据类型。
值类型:字符串(String)、数字 (Number)、布尔 (Boolean)、空(Null)、未定义(Undefined)、Symbol
。存放在栈内存中的简单数据段,数据大小确定,内存空间大小可以分配。
引用数据类型:对象 (Object) 、数组 (Array) 、函数 (Function) 。
存放在堆内存中的对象,在栈内存中存的是一个指针,这个指针指向堆内存一个位置。再从堆内存中取得所需的数据。
存储如下图:

什么是浅/深拷贝
讲完存储的方式,我们来讲讲浅拷贝和深拷贝
拷贝也就是我们常常讲的copy,ctrl+c,ctrl+v,那么我们来看看例子
当我们对分别值类型和引用类型进行赋值。
var a = 5
var b = a
b += 5
console.log('a=' + a,'b=' + b)
var arr=[1,2,3]
var brr=arr
brr.push(10)
console.log("arr为",arr)
console.log("brr为",brr)

现象:我们发现值类型并没有互相受到影响,然而数组(引用类型)brr数组添加元素的时候改变了arr数组。
解释分析:浅拷贝只会发生在引用类型身上,对于引用类型如果之进行简单的赋值,只会赋值指向堆内存的指针,这种称为浅拷贝。而深拷贝就是完全拷贝一个引用类型,为不是地址指针。
浅拷贝看下面这张原理图:

深拷贝实现
那么我们在赋值引用类型的时候肯定不能出现浅拷贝的现象,对原数据产生影响了。那么就要进行深拷贝
1.通过JSON.stringify和JSON.parse
可以深拷贝的数组和对象,但是不能拷贝函数,可以进行对象或者数组的嵌套拷贝。
缺点:无法实现对对象中方法的深拷贝
使用:
var brr=JSON.parse(JSON.stringify(arr))
例子:
var arr = {
name: '浪漫主义码农',
age: 20,
adress: ['jiangxi', 'changsha'],
friends: {
friend1: '张三',
friend2: '李四'
},
function(){
console.log("我是浪漫主义的对象")
}
}
var brr=JSON.parse(JSON.stringify(arr))
brr.name='法外狂徒张三'
brr.adress[0]='长沙'
console.log("arr为", arr)
console.log("brr为", brr)

2.扩展运算符
利用了对象的结构赋值特性方法。
缺点:无对对象里面嵌套的对象进行深拷贝,相当于只是对一层引用对象进行深拷贝
使用:
var brr={...arr}
例子:
var arr = {
name: '浪漫主义码农',
age: 20,
adress: ['jiangxi', 'changsha'],
friends: {
friend1: '张三',
friend2: '李四'
},
function(){
console.log("我是浪漫主义的对象")
}
}
var brr={...arr}
brr.name='法外狂徒张三'
brr.adress[0]='长沙'
console.log("arr为", arr)
console.log("brr为", brr)

3.手写递归深拷贝函数
完美解决
函数:
//使用递归实现深拷贝
function deepClone(obj) {
//判断拷贝的obj是对象还是数组
var objClone = Array.isArray(obj) ? [] : {};
if (obj && typeof obj === "object") { //obj不能为空,并且是对象或者是数组 因为null也是object
for (key in obj) {
if (obj.hasOwnProperty(key)) {
if (obj[key] && typeof obj[key] === "object") { //obj里面属性值不为空并且还是对象,进行深度拷贝
objClone[key] = deepClone(obj[key]); //递归进行深度的拷贝
} else {
objClone[key] = obj[key]; //直接拷贝
}
}
}
}
return objClone;
}
例子:
var arr = {
name: '浪漫主义码农',
age: 20,
adress: ['jiangxi', 'changsha'],
friends: {
friend1: '张三',
friend2: '李四'
},
fun: function(){
console.log("我是" + this.name + "的对象")
}
}
var brr = deepClone(arr)
brr.name = '法外狂徒张三'
brr.adress[0] = '长沙'
console.log("arr为", arr)
arr.fun()
console.log("brr为", brr)
brr.fun()
//使用递归实现深拷贝
function deepClone(obj) {
//判断拷贝的obj是对象还是数组
var objClone = Array.isArray(obj) ? [] : {};
if (obj && typeof obj === "object") { //obj不能为空,并且是对象或者是数组 因为null也是object
for (key in obj) {
if (obj.hasOwnProperty(key)) {
if (obj[key] && typeof obj[key] === "object") { //obj里面属性值不为空并且还是对象,进行深度拷贝
objClone[key] = deepClone(obj[key]); //递归进行深度的拷贝
} else {
objClone[key] = obj[key]; //直接拷贝
}
}
}
}
return objClone;
}

写在最后
如果有误,欢迎大佬在评论区留言。
“远赴人间惊鸿宴,一睹人间盛世颜”
一个心怀浪漫宇宙,也珍惜人间日常的码农

js深拷贝你还不会吗的更多相关文章
- js 深拷贝和浅拷贝
js 深拷贝和浅拷贝 先举一下项目中遇到的两个例子: 例子1: var json = $.parseJSON(data.data);//data.data是接口返回的值var a = json.cha ...
- JS你可能还不知道的一些知识点(一)
js程序是用Unicode字符集编写的, 2.转义字符:反斜线 1 2 3 4 function Test(){ var s='you\'re right,it can\'t be a quote ...
- 老生常谈之js深拷贝与浅拷贝
前言 经常会在一些网站或博客看到"深克隆","浅克隆"这两个名词,其实这个很好理解,今天我们就在这里分析一下js深拷贝和浅拷贝. 浅拷贝 我们先以一个例子来说明 ...
- 关于JS深拷贝和浅拷贝
最近在前端开发中遇到一些问题,就是数组中的某个对象或某个对象的值改变之后,在不刷新页面的时候需要重新渲染值时,页面显示的还是原来的数据.比如: data{ A:[{id:1,num:1},{id:2, ...
- JS 深拷贝
使用递归进行深拷贝 http://lingyu.wang/2014/03/20/js-interview-1/ Object.prototype.deepClone = function() { va ...
- 理解JS深拷贝
前言: JS的拷贝(copy),之所以分为深浅两种形式,是因为JS变量的类型存在premitive(字面量)与reference(引用)两种区别.当然,大多数编程语言都存在这种特性. 众所周知,内存包 ...
- [转] js深拷贝和浅拷贝
一.数组的深浅拷贝 在使用JavaScript对数组进行操作的时候,我们经常需要将数组进行备份,事实证明如果只是简单的将它赋予其他变量,那么我们只要更改其中的任何一个,然后其他的也会跟着改变,这就导致 ...
- JS动态呈现还可以输入字数
现在觉得当我们使用js或者jquery来呈现一个动态效果时,主要还是要想清楚它的思想.它的原理.而动态呈现输入字数,其实就是给它设置一个最大输入字数,然后获取已输入的字数,自然想做什么都可以. < ...
- 由js深拷贝引起的对内存空间的一些思考
数据类型 js常用数据类型分为基本类型和引用类型 基本类型:null.undefined.数值型.字符串型.布尔型 引用类型:数组.对象 内存空间 var a = [1, 2, 3]; var b = ...
随机推荐
- 解决联想R720双系统Ubuntu16.04的无线网卡开启问题及信号不稳定
问题一:1.问题描述笔记本型号:Lenovo r720笔记本(i5-7300hq,gtx1060 maxq 6g),默认装入Win10系统,然而当装入Ubuntu16.04双系统时,会出现无线网卡(型 ...
- bug 找不到或无法加载主类main.java.*
开发时遇到的的一个问题,不知道是什么引起的,一个maven springboot 的项目,主类启动的时候报错,说没找到 主类,起先怀疑是springboot的问题,随手写一个单独的类,有main方法, ...
- ASP.NET Core 学习笔记 第三篇 依赖注入框架的使用
前言 首先感谢小可爱门的支持,写了这个系列的第二篇后,得到了好多人的鼓励,也更加坚定我把这个系列写完的决心,也能更好的督促自己的学习,分享自己的学习成果.还记得上篇文章中最后提及到,假如服务越来越多怎 ...
- vue3 专用 indexedDB 封装库,基于Promise告别回调地狱
IndexedDB 的官网 https://developer.mozilla.org/zh-CN/docs/Web/API/IndexedDB_API 这个大概是官网吧,原始是英文的,现在陆续是出中 ...
- InstallScript脚本语言基本知识(一)
1.自定义函数 1 //函数的声明:prototype 返回值 函数名(形参类型1,...) 2 export prototype STRING GetPreDir(STRING); 3 4 //函数 ...
- 洛谷4172 WC2006水管局长(LCT维护最小生成树)
这个题和魔法森林感觉有很相近的地方啊 同样也是维护一个类似最大边权最小的生成树 但是不同的是,这个题是有\(cut\)和询问,两种操作.... 这可如何是好啊? 我们不妨倒着来考虑,假设所有要\(cu ...
- 舌头算法的C++实现
观察生活,我们不难发现,吃饭的时候,有时候左边的东西会到右边来,这是为什么呢?就是舌头的作用了. 下面的代码将模拟舌头的运动: #include <iostream> #include & ...
- Billu_b0x2内网渗透(多种提权方法)靶场-vulnhub
个人博客阅读体验更佳 本次来试玩一下vulnhub上的Billu_b0x2,下载地址. 下载下来后是 .ova 格式,建议使用vitualbox进行搭建,vmware可能存在兼容性问题.靶场推荐使用N ...
- 【转】对于编译程序时出现“Deprecated declaration ultrasonic_Init - give arg types”的解决办法
编译程序时出现"Deprecated declaration ultrasonic_Init - give arg types"中文释义:给定函数的参数的类型过时, 解决办法: 在 ...
- 初始HTML05
HTML 表单控件属性 表单控件可设置以下标签属性 属性名 取值 type 设置控件类型 name 设置控件名称,最终与值一并发送给服务器 value 设置控件的值 placeholder 设置输入框 ...