最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript實現(xiàn)多層深拷貝的簡單方法

 更新時間:2025年07月29日 10:18:19   作者:景籬  
這篇文章主要為大家詳細介紹了JavaScript中實現(xiàn)多層深拷貝的幾個簡單方法,文中的示例代碼簡潔易懂,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

1.使用Json轉(zhuǎn)換的方式

let a = [1,2,3,[4,5]]
let b = Json.parse(Json.stringify(a))

缺點:

  • 如果嵌套的是函數(shù)類型就不能用,會被忽略
  • undefined不能用,會被忽略
  • Symbol不能用,會被忽略
  • Date對象會變成字符串
  • 無法處理循環(huán)引用(會報錯)

2.如果嵌套的有函數(shù)類型

let obj = {
name:"Tom",
age:18,
fn(){
console.log("age:",this.age)
},
tt:{project:"kkk"},
aa:[1,2,3]
}

let obj2 = {...obj} // 淺拷貝:只復(fù)制第一層屬性值(如字符串、數(shù)字等),對于嵌套的對象或數(shù)組,復(fù)制的是引用地址
obj.fn = function(){
console.log("++age:",++this.age)}

obj.fn()
obj2.fn()

obj.tt.project = "yyy"
console.log("obj",obj.tt.project)
console.log("obj2",obj2.tt.project)

obj.aa[0] = 5
console.log("obj",obj.aa)
console.log("obj2",obj2.aa)

注意到當(dāng)修改函數(shù)的值時,數(shù)據(jù)不會產(chǎn)生相互干擾,但是當(dāng)修改數(shù)組或者對象的值會有干擾,因為數(shù)組或者對象復(fù)制過去的一層都是地址,函數(shù)是因為我們修改的方式相當(dāng)于重寫一個函數(shù),因此你新的函數(shù)會在內(nèi)存中開辟一個新的存儲空間。

3.使用遞歸實現(xiàn)深拷貝

實現(xiàn)思路:

  • 邊界處理:如果是null或者非object類型,直接返回
  • 處理循環(huán)引用:存儲已拷貝過的對象,避免死循環(huán)
  • 創(chuàng)建新容器:判斷是數(shù)組還是對象,創(chuàng)建相應(yīng)的空容器[]或者{}
  • 遞歸拷貝:遍歷原始對象的屬性,遞歸調(diào)用deepClone復(fù)制給新容器
let a = [1,2,3]
console.log(typeof a) //object

let b=null
console.log(typeof b)//object
let c=undefined
console.log(typeof c)//undefined

/**
 * 深拷貝函數(shù):遞歸實現(xiàn)
 * @param {any} oldData 需要拷貝的數(shù)據(jù),可以是對象、數(shù)組或基本類型
 * @return {any} 返回拷貝后的新數(shù)據(jù),與原數(shù)據(jù)無引用關(guān)系
 */
function deepClone(oldData) {
  // 判斷當(dāng)前處理的數(shù)據(jù)是否為對象類型,并且不是 null(因為 typeof null === 'object')
  if (typeof oldData === 'object' && oldData != null) {
    // 根據(jù)原始數(shù)據(jù)是數(shù)組還是對象創(chuàng)建一個新的空數(shù)組或空對象作為結(jié)果容器
    let res = Array.isArray(oldData) ? [] : {};

    // 遍歷原始對象的所有自有屬性(不包括繼承來的屬性)
    for (let k in oldData) {
      if (oldData.hasOwnProperty(k)) {
        // 對當(dāng)前屬性值遞歸調(diào)用 deepClone 函數(shù)進行深拷貝
        // 并將返回的結(jié)果賦值給結(jié)果對象/數(shù)組對應(yīng)的鍵
        res[k] = deepClone(oldData[k]);
      }
    }

    // 返回已經(jīng)完成深拷貝的對象/數(shù)組
    return res;
  } else {
    // 如果當(dāng)前數(shù)據(jù)是基本類型(如 number, string, boolean)或者函數(shù)等,則直接返回原值
    // 因為基本類型在賦值時是值傳遞,不會產(chǎn)生引用問題
    return oldData;
  }
}

4.structuredClone()

const original = {a:1, b: {c:2}, d:new Date()};
const deepCopy = structuredClone(original)

deepCopy.b.c = 20; 

console.log(original.b.c)  //2
console.log(original.d.getTime() === deepCopy.d.getTime()) //true (Date被正確克隆了)

優(yōu)點:

  • 內(nèi)置的全局函數(shù),無需引庫
  • 專為深拷貝設(shè)計,性能好
  • 支持循環(huán)引用
  • 支持多種復(fù)雜類型,如Date、Map、Set、正則等

缺點:

  • 無法拷貝函數(shù)
  • 無法拷貝Error對象/DOM節(jié)點

5.知識延展

javascript 深拷貝 (多層嵌套解決方案)

數(shù)組的幾種方法深拷貝總結(jié)

var arr = [3,4,1,6,4]//準備好一個數(shù)組
 
var arr2 = arr.concat()//concat合并方法
 
var arr4 = JSON.parse(JSON.stringify(arr))//用JSON方法轉(zhuǎn)換
 
var arr5 = arr.slice(0)//slice拷貝方法
 
var [...arr6] =arr;//擴展運算符方法
 
var arr7 = copyArr(arr)//萬能的for循環(huán)
    function copyArr(arr){
        let res = []
        for(let i=0;i<arr.length;i++){
            res.push(arr[i])
        }
        return res 
    }
 
 
//冒泡排序 
   for(var j = 0;j<arr.length-1;j++){//// 遍歷數(shù)組,arr.length - 1表示要遍歷的次數(shù)
       for(var i = 0;i<arr.length-1-j;i++){
        // i<arr.length-1-j 是因為當(dāng)?shù)谝淮?,找到最大?shù),放到最后,那么下一次,遍歷的時候就不用吧最后一位算上,因為他已經(jīng)是最大的
            var done = true;//設(shè)置一個標(biāo)志位,減少不必要的循環(huán)
            if(arr[i]>arr[i+1]){//當(dāng)前數(shù)字大于后一位數(shù)組 位置調(diào)換
                var temp = arr[i]
                arr[i] =arr[i+1]
                arr[i+1] = temp
                done = false
                
            }
        }
        if(done){//調(diào)換位置后跳出本次循環(huán) 
           break;//減少不必要的排序,提高性能。
        }
   }
//冒泡排序思想:每一次對比相鄰兩個數(shù)據(jù)的大小,小的排在前面,如果前面的數(shù)據(jù)比后面的大就交換這兩個數(shù)的位置
console.log('經(jīng)過排序的原數(shù)組:'+arr)
console.log('concat方法:'+arr2)
console.log('轉(zhuǎn)換為json再轉(zhuǎn)為對象:'+arr4)
console.log('slice方法:'+arr5)
console.log('ES6擴展運算符方法:'+arr6)
console.log('萬能的for方法:'+arr7)

上面實現(xiàn)的幾種方式寫在了一起 搞不明白方法的可以看下我前幾天發(fā)的數(shù)組方法帖子。

對象的深拷貝

對象的深拷貝相比數(shù)組也沒有困難許多,列舉三種個方法。

1.萬能的for循環(huán)

var obj = {
  name: 'wayne',
  sex: 'man',
  old: '23'
}
var obj2 = copyObj(obj)
function copyObj(obj) {
  let res = {}
  for (var key in obj) {
    res[key] = obj[key]
  }
  return res
}

2.JSON方法

var obj = {
  name: 'wayne',
  sex: 'man',
  old: '23'
}
var obj2 = JSON.parse(JSON.stringify(obj))
//原理沒什么好解釋的,實在是夠簡單粗暴

JSON.stringify()方法將對象轉(zhuǎn)化為字符串,但只會處理簡單屬性和簡單屬性數(shù)組,constructor屬性丟失了

3.ES6擴展運算符

var obj = {
  name: 'wayne',
  sex: 'man',
  old: '23'
}
var { ...obj2 } = obj

對象的深拷貝推薦使用es6提供的擴展運算符的方法

到此這篇關(guān)于JavaScript實現(xiàn)多層深拷貝的簡單方法的文章就介紹到這了,更多相關(guān)JavaScript深拷貝內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

当阳市| 淮安市| 绩溪县| 屏东市| 东阳市| 长葛市| 蓬莱市| 阳山县| 南召县| 邵阳县| 博白县| 惠州市| 大渡口区| 尚义县| 特克斯县| 克拉玛依市| 资兴市| 镇赉县| 磴口县| 大渡口区| 资溪县| 肥东县| 杭锦后旗| 甘肃省| 揭阳市| 哈巴河县| 平顶山市| 霍州市| 慈利县| 米脂县| 隆回县| 区。| 兰考县| 大城县| 永嘉县| 天峻县| 日照市| 民丰县| 郑州市| 隆德县| 中超|