js深拷貝淺拷貝

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
 
</body>
<script>
  // 在JS中,數(shù)據(jù)類型分為基本數(shù)據(jù)類型和引用數(shù)據(jù)類型兩種,對(duì)于基本數(shù)據(jù)類型來(lái)說(shuō),它的值直接存儲(chǔ)在棧內(nèi)存中,
  // 而對(duì)于引用類型來(lái)說(shuō),它在棧內(nèi)存中僅僅存儲(chǔ)了一個(gè)引用,而真正的數(shù)據(jù)存儲(chǔ)在堆內(nèi)存中


  // 當(dāng)基本類型實(shí)現(xiàn)淺拷貝,存在棧內(nèi)存中,那么相互獨(dú)立,互不影響。
  // 當(dāng)復(fù)雜類型實(shí)現(xiàn)淺拷貝,新對(duì)象與舊對(duì)象仍然同時(shí)指向堆內(nèi)存的同一屬性,互不獨(dú)立,相互影響。

  // 基本數(shù)據(jù)類型
  var a = "1";
  var b = a;
  a = 2;
  console.log(b);


  // 引用數(shù)據(jù)類型
  var arr = [1,2,3];
  var newArr = copy(arr);  //[1,2,3]
  newArr.push(4); //[1,2,3,4]
  console.log(arr); //[1,2,3,4]
  // 當(dāng)我們創(chuàng)建arr數(shù)組時(shí),arr被分配到了堆內(nèi)存中,在棧內(nèi)存留下可以尋找到的指針,
  // 也就是說(shuō)當(dāng)我們創(chuàng)建新數(shù)組newArr時(shí),賦予newArr的是arr在棧中的地址(指針),
  // 其實(shí)仍與舊數(shù)組arr共享同一個(gè)內(nèi)存,所以修改新數(shù)組newArr后,舊數(shù)組arr也會(huì)被修改


  // 深拷貝
  // 它可以將復(fù)雜類型的數(shù)據(jù)相互獨(dú)立出來(lái),互不影響
  // 深拷貝不會(huì)拷貝引用類型的引用,而是將引用類型的值全部拷貝一份,形成一個(gè)新的引用類型,
  // 這樣就不會(huì)發(fā)生引用錯(cuò)亂的問(wèn)題,使得我們可以多次使用同樣的數(shù)據(jù),而不用擔(dān)心數(shù)據(jù)之間會(huì)起沖突

  // 1、
  function copy(obj) {
    if(typeof obj == "object") { //判斷是否復(fù)雜類型
       var result = obj.constructor == Array ? [] : {};//判斷數(shù)組類型或是object,數(shù)組即result=[],object即result={}
        for(let i in obj) {
            result[i] = typeof obj[i] == "object" ? copy(obj[i]) : obj[i]//判斷數(shù)據(jù)每一項(xiàng)是否是object
        }
    } else {
        var result = obj //基本類型直接拷貝
    }
  return result;
}
 // 2、
function deepClone(target) {
    // 定義一個(gè)變量
    let result;
    // 如果當(dāng)前需要深拷貝的是一個(gè)對(duì)象的話
    if (typeof target === 'object') {
    // 如果是一個(gè)數(shù)組的話
        if (Array.isArray(target)) {
            result = []; // 將result賦值為一個(gè)數(shù)組,并且執(zhí)行遍歷
            for (let i in target) {
                // 遞歸克隆數(shù)組中的每一項(xiàng)
                result.push(deepClone(target[i]))
            }
         // 判斷如果當(dāng)前的值是null的話;直接賦值為null
        } else if(target===null) {
            result = null;
         // 判斷如果當(dāng)前的值是一個(gè)RegExp對(duì)象的話,直接賦值    
        } else if(target.constructor===RegExp){
            result = target;
        }else {
         // 否則是普通對(duì)象,直接for in循環(huán),遞歸賦值對(duì)象的所有值
            result = {};
            for (let i in target) {
                result[i] = deepClone(target[i]);
            }
        }
     // 如果不是對(duì)象的話,就是基本數(shù)據(jù)類型,那么直接賦值
    } else {
        result = target;
    }
     // 返回最終結(jié)果
    return result;
}
</script>
</html>


 

作者:Vam的金豆之路

主要領(lǐng)域:前端開(kāi)發(fā)

我的微信:maomin9761

微信公眾號(hào):前端歷劫之路