JavaScript深拷贝和浅拷贝 及 JSON.parse(JSON.stringify()) 的缺陷

Posted 奥特曼 

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript深拷贝和浅拷贝 及 JSON.parse(JSON.stringify()) 的缺陷相关的知识,希望对你有一定的参考价值。

目录

一、理解拷贝

二、基本数据类型拷贝

三、浅拷贝(shallow  clone)

对象浅拷贝

(1)依次赋值

(2)for..in 遍历

(3)Object.assign(目标对象,要拷贝的对象)

(4)展开运算符

缺陷:只能拷贝外层不能拷贝内层

 数组浅拷贝

(1)依次赋值

(2)展开运算符

(3)slice

(4)map

四、深拷贝

对象数组深拷贝

(1)递归

(2)JSON.parse(JSON.stringify())


一、理解拷贝

拷贝就像我们平常cv一些文件、代码 复制了一份新的就叫拷贝。 换成js代码就变成了基本数据类型和引用数据类型的拷贝。

javascript中我们定义的简单数据类型会存到栈(stack)内存中,包括引用类型的指针,而这个指针指向的地方是在堆(heap)内存中。也通常理解为,简单数据类型存在栈中,引用数据类型存在堆中

二、基本数据类型拷贝

基本数据类型没什么好说的,通过一个变量赋值给一个变量就已经拷贝完成了

        let a = 1
        let b = a

 把a赋值给b之后 再去操作a并不会影响b   你可以理解为 a 和b 是两个不同的区域,但都是存在栈内存里。

        let a = 1
        let b = a
        a=5
        console.log(b); //1
        console.log(a); //5

三、浅拷贝(shallow  clone)

浅拷贝只能拷贝复杂数据类型的指针,并不能改变复杂数据类型的地址,只能拷贝外层,并不能彻底拷贝,例如数组中还有数组(对象),(准确来说是外层引用数据类型)

对象浅拷贝

(1)依次赋值

优点:数量较少的时候使用方便、简单,缺点:遇到对象或数组键比较多时,操作不方便

        let obj = 
            a: name: 'abc',
            b: 2
        
        let newObj = 
        newObj.a=obj.a
        newObj.b=obj.b

(2)for..in 遍历

        let obj = 
            a: name: 'abc',
            b: 2
        
       let newObj =  
       for (const key in obj) 
          newObj[key]=obj[key]
       

(3)Object.assign(目标对象,要拷贝的对象)

        let obj = 
            a:name:'奥特曼',
            b:2
        
        let newObj= 
        Object.assign(newObj,obj)

(4)展开运算符

         let obj = 
            a: name: 'abc',
            b: 2
        
        let newObj = 
        newObj = ...obj

缺陷:只能拷贝外层不能拷贝内层

浅拷贝只能拷贝最外层的引用地址,并不能拷贝内层的引用地址  

修改最内层的数据 另一个也会改变,因为指针指向的的都是同一个内存地址

        newObj.a.name='bcd'
        console.log(obj);    //a: name: "bcd", b: 2
        console.log(newObj); //a: name: "bcd", b: 2

 数组浅拷贝

(1)依次赋值

        let arr  =  [1,name:'abc']
        let newArr = []
        newArr[0]=arr[0] 
        newArr[1]=arr[1] 

(2)展开运算符

        let arr  =  [1,name:'abc']
        let newArr = [...arr]

(3)slice

       let arr  =  [1,name:'abc']
        let newArr = arr.slice(0)

(4)map

        let arr  =  [1,name:'abc']
        let newArr = arr.map(it=>it)

同样修改数组中内存的数据 另一个数组的内存数据也会改变

        arr[1].name='bcd' 
        console.log(arr);// 1, name: "bcd"
        console.log(newArr);// 1, name: "bcd"

四、深拷贝

深拷贝:不光外层的引用地址该变了 内层的引用数据类型也发生改变

对象数组深拷贝

(1)递归

   obj =  
            a: name: 'abc',
            b: 2 
         
        function fn(obj) 
            let newObj = 
            // 如果不是对象直接返回 
            if(typeof obj !=='object')
                return '不是一个对象'
            else 
                // 是对象就对每一项进行遍历 
                for (const key in obj) 
                    // 判断内部是否为对象  如果不是对象就进行递归 
                    if(typeof obj[key] ==='object')
                        newObj[key]=fn(obj[key])
                    else
                        newObj[key]=obj[key]
                    
                
            
            return newObj
        

优化 

  obj = 
            a:  name: 'abc'  ,
            b: 2
        
        function fn(obj) 
            let newObj = 
            if(typeof obj !=='object') return '不是一个对象'
                for (const key in obj) 
                    typeof obj[key] ==='object'? newObj[key]=fn(obj[key]): newObj[key]=obj[key]
                    
            return newObj
        
         let newObj = fn(obj)

 这时候在修改对象里面的引用类型时 就不会影响另一个对象

        newObj.a.name='bcd'
        console.log(obj);
        console.log(newObj);

(2)JSON.parse(JSON.stringify())

     let newObj = JSON.parse(JSON.stringify(obj))

这个深拷贝我们经常会在网上看到,但也不是没有缺陷 

  obj = 
            a:NaN,
            b: undefined,
            c:new Date(),
            d:new RegExp(/\\d/),
            d:new Error(),
            e:Infinity
        
        console.log(obj);
        let newObj = JSON.parse(JSON.stringify(obj))
        console.log(newObj);

对比图

JSON.parse(JSON.stringify())拷贝后的缺陷:

  • NaN          ===》null
  • undefined ===》 空
  • 时间戳      ===》字符串时间
  • 错误信息  ===》 空对象
  • Infinity      ===》null

以上是关于JavaScript深拷贝和浅拷贝 及 JSON.parse(JSON.stringify()) 的缺陷的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript深拷贝和浅拷贝的总结(含义区别及实现)

JSON对象的深拷贝和浅拷贝

python深拷贝和浅拷贝的区别

Javascript中的深拷贝和浅拷贝

Javascript学习之深拷贝和浅拷贝详解

JavaScript的深拷贝和浅拷贝