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深拷贝你还不会吗的更多相关文章

  1. js 深拷贝和浅拷贝

    js 深拷贝和浅拷贝 先举一下项目中遇到的两个例子: 例子1: var json = $.parseJSON(data.data);//data.data是接口返回的值var a = json.cha ...

  2. JS你可能还不知道的一些知识点(一)

    js程序是用Unicode字符集编写的, 2.转义字符:反斜线 1 2 3 4 function Test(){   var s='you\'re right,it can\'t be a quote ...

  3. 老生常谈之js深拷贝与浅拷贝

    前言 经常会在一些网站或博客看到"深克隆","浅克隆"这两个名词,其实这个很好理解,今天我们就在这里分析一下js深拷贝和浅拷贝. 浅拷贝 我们先以一个例子来说明 ...

  4. 关于JS深拷贝和浅拷贝

    最近在前端开发中遇到一些问题,就是数组中的某个对象或某个对象的值改变之后,在不刷新页面的时候需要重新渲染值时,页面显示的还是原来的数据.比如: data{ A:[{id:1,num:1},{id:2, ...

  5. JS 深拷贝

    使用递归进行深拷贝 http://lingyu.wang/2014/03/20/js-interview-1/ Object.prototype.deepClone = function() { va ...

  6. 理解JS深拷贝

    前言: JS的拷贝(copy),之所以分为深浅两种形式,是因为JS变量的类型存在premitive(字面量)与reference(引用)两种区别.当然,大多数编程语言都存在这种特性. 众所周知,内存包 ...

  7. [转] js深拷贝和浅拷贝

    一.数组的深浅拷贝 在使用JavaScript对数组进行操作的时候,我们经常需要将数组进行备份,事实证明如果只是简单的将它赋予其他变量,那么我们只要更改其中的任何一个,然后其他的也会跟着改变,这就导致 ...

  8. JS动态呈现还可以输入字数

    现在觉得当我们使用js或者jquery来呈现一个动态效果时,主要还是要想清楚它的思想.它的原理.而动态呈现输入字数,其实就是给它设置一个最大输入字数,然后获取已输入的字数,自然想做什么都可以. < ...

  9. 由js深拷贝引起的对内存空间的一些思考

    数据类型 js常用数据类型分为基本类型和引用类型 基本类型:null.undefined.数值型.字符串型.布尔型 引用类型:数组.对象 内存空间 var a = [1, 2, 3]; var b = ...

随机推荐

  1. P4345-[SHOI2015]超能粒子炮·改【Lucas定理,类欧】

    正题 题目链接:https://www.luogu.com.cn/problem/P4345 题目大意 \(T\)组询问,给出\(n,k\)求 \[\sum_{i=0}^{k}\binom{n}{i} ...

  2. UVa/数组与字符串习题集

    UVa-272. Description: TEX is a typesetting language developed by Donald Knuth. It takes source text ...

  3. break和continue关键字

    什么是break break 跳出最里层的循环,并且继续执行该循环下面的语句 就是强制退出循环 示例 package struct; public class ForDemo05 { public s ...

  4. PTA数据结构 习题3.6 一元多项式的乘法与加法运算 (20分)

    一元多项式的乘法与加法运算 https://pintia.cn/problem-sets/434/problems/5865 设计函数分别求两个一元多项式的乘积与和. 时间限制:200 ms 内存限制 ...

  5. Java(22)常用API一

    1 API 1.1 API概述 什么是API ​ API (Application Programming Interface) :应用程序编程接口 java中的API ​ 指的就是 JDK 中提供的 ...

  6. CAM对象样式表

    CAM对象样式表 121 160 UF_machining_task_type UF_mach_order_task_subtype 112 UF_machining_null_grp_type 无 ...

  7. Linux中使用dd制作文件的.img

    dd if=/dev/zero of=new_img.img bs=1M count=20   //生成20M的文件,bs块的大小,count块的数量 mkfs.ext3 new_img.img  / ...

  8. 在hive中使用COALESCE进行空值处理

    COALESCE (expression_1, expression_2, ...,expression_n)依次参考各参数表达式,遇到非null值即停止并返回该值.如果所有的表达式都是空值,最终将返 ...

  9. 第五章第四周习题: Transformers Architecture with TensorFlow

    目录 Transformer Network Packages 1 - Positional Encoding 1.1 - Sine and Cosine Angles Exercise 1 - ge ...

  10. BUAA2020软工作业(一)——谈谈我和计算机的缘分

    项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 第一次作业-热身! 我在这个课程的目标是 进一步提高自己的编码能力,工程能力 这个作业在哪个具体方 ...