1. 程式人生 > >javascript實現引用數據類型的深拷貝和淺拷貝詳解

javascript實現引用數據類型的深拷貝和淺拷貝詳解

var struct blue name 拷貝 ont javascrip ceo ole

關於引用類型值的詳解,請看另一篇隨筆 https://www.cnblogs.com/jinbang/p/10346584.html

深拷貝和淺拷貝,也就是引用數據類型棧和堆的知識點。深淺拷貝的原型都是Object,深拷貝指向的棧內存不一樣,淺拷貝指向的棧內存一樣): 如何區分深拷貝與淺拷貝,就是假設B復制了A,當修改A時,看B是否會發生變化,如果B沒有發生變化,說明是深拷貝。如果B也跟著發生了變化,說明是淺拷貝。
      let obj = { name: "jin", arr: ["red","blue","black"]};
      let obj1 = {};
      Object.defineProperties(obj1, Object.getOwnPropertyDescriptors(obj)); 
// 深拷貝 Object.assign(obj1, obj); // 深拷貝 obj1 = JSON.parse(JSON.stringify(obj)); // 深拷貝 obj1 = deepCopy(obj); // 使用到深拷貝函數 obj1 = obj; // 淺拷貝 obj1 = Object.assign(obj); // 淺拷貝

下面是deepCopy()深拷貝函數,其中使用到了判斷變量的類型函數

      // 判斷變量的類型
      function getType(obj){
        let str = Object.prototype.toString.call(obj); //
檢測基本類型值,引用類型值的類型 let map = { ‘[object Boolean]‘: ‘boolean‘, ‘[object Number]‘: ‘number‘, ‘[object String]‘: ‘string‘, ‘[object Function]‘: ‘function‘, ‘[object Array]‘: ‘array‘, ‘[object Date]‘: ‘date‘, ‘[object RegExp]‘: ‘regExp‘,
‘[object Undefined]‘: ‘unfefined‘, ‘[object Null]‘: ‘null‘, ‘[object Object]‘: ‘object‘ }; if(obj instanceof Element){ return ‘element‘; } return map[str]; } // 深拷貝函數 function deepCopy(p){ let obj; let str = getType(p); if(str === ‘array‘){ obj = []; for(let i=0;i<p.length;i++){ // obj.push(p[i]); // 不能這樣寫,因為會把array的堆內存也會復制過去 obj.push(arguments.callee(p[i])); //回調自己 } }else if(str === ‘object‘){ obj = {}; for(let i in p){ // obj[i] = p[i]; // 不能這樣寫,因為會把object的堆內存也會復制過去 obj[i] = arguments.callee(p[i]); //回調自己 } } else { return p; } return obj; }

需要特別註意的是,使用JSON.parse(JSON.stringify(x))不是一個很好的選擇,也算是它們的坑吧:

對象是由構造函數生成的:會丟棄對象的constructor,因為JSON.stringify()只能序列化對象的可枚舉的自有屬性 時間對象:變成字符串 RegExp,Error對象:變成空對象 函數,undefined:會被丟失 NaN,Infinity和-Infinity:變成null
function Person(name){
      this.name = name;
    }
    var person = new Person(‘liai‘);
    
    var test = {
      name: ‘jin‘,
      person: person, //對象是由構造函數生成的:會丟棄對象的constructor
      date: new Date(), //序列化後返回是字符串,不是時間對象
      regexp: new RegExp(‘\\w+‘), //序列化後返回空對象:{}
      err: new Error(),  //序列化後返回空對象:{}
      fun: function(){}, //序列化後會丟失
      undef: undefined, //序列化後會丟失
      nun: NaN, //序列化後返回null
    };
    console.log(test);
    console.log(JSON.parse(JSON.stringify(test)));

javascript實現引用數據類型的深拷貝和淺拷貝詳解