js深拷貝你還不會嗎


js深拷貝

在講正題之前我們要先了解數據存儲的方式

數據存儲方式

在講之前我們要先知道值類型和引用類型的存儲方式。

在JavaScript數據類型中有兩種數據類型。

值類型字符串(String)、數字 (Number)、布爾 (Boolean)、空(Null)、未定義(Undefined)、Symbol

。存放在棧內存中的簡單數據段,數據大小確定,內存空間大小可以分配。

引用數據類型對象 (Object)數組 (Array)函數 (Function)

存放在堆內存中的對象,在棧內存中存的是一個指針,這個指針指向堆內存一個位置。再從堆內存中取得所需的數據。

存儲如下圖:

image

什么是淺/深拷貝

講完存儲的方式,我們來講講淺拷貝和深拷貝

拷貝也就是我們常常講的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)

image

現象:我們發現值類型並沒有互相受到影響,然而數組(引用類型)brr數組添加元素的時候改變了arr數組。

解釋分析:淺拷貝只會發生在引用類型身上,對於引用類型如果之進行簡單的賦值,只會賦值指向堆內存的指針,這種稱為淺拷貝。而深拷貝就是完全拷貝一個引用類型,為不是地址指針。

淺拷貝看下面這張原理圖:

image

深拷貝實現

那么我們在賦值引用類型的時候肯定不能出現淺拷貝的現象,對原數據產生影響了。那么就要進行深拷貝

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)

image

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)

image

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;
     }

image

寫在最后

如果有誤,歡迎大佬在評論區留言。

💌 “遠赴人間驚鴻宴,一睹人間盛世顏” 💌

一個心懷浪漫宇宙,也珍惜人間日常的碼農

image


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM