深拷貝和淺拷貝的區別是什么?實現一個深拷貝


JS的基本數據類型

  • 基本數據類型:String,Boolean,Number,Undefined,Null;
  • 引用數據類型:Object(Array,Date,RegExp,Function);

淺拷貝

  • 淺拷貝是會將對象的每個屬性進行依次復制,但是當對象的屬性值是引用類型時,實質復制的是其引用,當引用指向的值改變時也會跟着變化。
  • Object.assign、 擴展運算符 ... 、 Array.prototype.slice()、 Array.prototype.concat() 等

深拷貝

  • 深拷貝復制變量值,對於引用數據,則遞歸至基本類型后,再復制。
  • 深拷貝后的對象與原來的對象是完全隔離的,互不影響,對一個對象的修改並不會影響另一個對象

示例:

    let obj = {
        name : 'Michael',
        age  :  18 ,
        others : {
            hobbies : ['basketball','gambling'],
            team : 'Bulls',
        },
    }
    let [newObj,newObj2] = [Object.assign({},obj),{...obj}]
    
    obj.name = 'Kobe';
    obj.others.team = 'Lakers';

    console.log(obj)
console.log(newObj)
console.log(newObj2)

我們能看出:

  • newObj及newObj2的others為引用數據類型,因此與原對象obj的屬性值指向同一塊內存地址,修改原對象的others內的內容,新對象的內容也會更改
  •  第一層的屬性值為基本數據類型(String),修改原對象,對新對象不造成影響

 

因此 深拷貝與淺拷貝的區別為

  • 淺拷貝當第一層的屬性值是基本數據類型時,新的對象和原對象互不影響,但是如果第一層的屬性值是引用數據類型時,那么新對象和原對象的屬性值其指向的是同一塊內存地址。
  • 深拷貝會另外創造一個一模一樣的對象,新對象跟原對象不共享內存,修改新對象不會改到原對象;

深拷貝的代碼實現

  1. 如果是基本數據類型,直接返回
  2. 如果是復雜數據類型,遞歸。
  3. 如果是RegExp 或者 Date 類型,返回對應類型
   let obj = {
        name: 'Michael',
        age: 18,
        others: {
            hobbies: ['basketball', 'gambling'],
            team: 'Bulls',
        },
    }
    // 遞歸拷貝
    function deepClone(obj) {
        if (obj instanceof RegExp) return new RegExp(obj);
        if (obj instanceof Date) return new Date(obj);
        if (obj === null || typeof obj !== 'object') return obj //如果不是引用類型則直接返回
        let newObj = new obj.constructor();    //如果obj是數組,newObj=[];如果obj是對象,newObj={}
        for (let key in obj) {
            if (obj.hasOwnProperty(key)) {    //是否是自身的對象
                newObj[key] = deepClone(obj[key])   //賦值
            }
        }
        return newObj
    }
    const copyObj = deepClone(obj);
    obj.others.team = 'Lakers';
    console.log(obj,copyObj)

經比較:深拷貝后修改原對象的值並不會改變新對象的值

 


免責聲明!

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



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