1. 程式人生 > >JSON.parse(JSON.stringify()) 實現對對象的深拷貝

JSON.parse(JSON.stringify()) 實現對對象的深拷貝

title pan ttr ror i++ 得到 epc 將不 ins

JSON.parse(JSON.stringify(obj))我們一般用來深拷貝,其過程說白了 就是利用JSON.stringify 將js對象序列化(JSON字符串),再使用JSON.parse來反序列化(還原)js對象;序列化的作用是存儲(對象本身存儲的只是一個地址映射,如果斷電,對象將不復存在,因此需將對象的內容轉換成字符串的形式再保存在磁盤上 )和傳輸(例如 如果請求的Content-Typeapplication/x-www-form-urlencoded,則前端這邊需要使用qs.stringify(data)來序列化參數再傳給後端,否則後端接受不到; ps: Content-Type

application/json;charset=UTF-8或者 multipart/form-data 則可以不需要 );我們在使用 JSON.parse(JSON.stringify(xxx))時應該註意一下幾點:
1、如果obj裏面有時間對象,則JSON.stringify後再JSON.parse的結果,時間將只是字符串的形式。而不是時間對象;

      var test = {
        name: ‘a‘,
        date: [new Date(1536627600000), new Date(1540047600000)],
      };

      let b;
      b = JSON.parse(JSON.stringify(test))
技術分享圖片 test 結果.png 技術分享圖片 b的結果 技術分享圖片 測試b和test類型

2、如果obj裏有RegExp、Error對象,則序列化的結果將只得到空對象;

      const test = {
        name: ‘a‘,
        date: new RegExp(‘\\w+‘),
      };
      // debugger
      const copyed = JSON.parse(JSON.stringify(test));
      test.name = ‘test‘
      console.error(‘ddd‘, test, copyed)
技術分享圖片 image.png

3、如果obj裏有函數,undefined,則序列化的結果會把函數或 undefined丟失;

      const test = {
        name: ‘a‘,
        date: function hehe() {
          console.log(‘fff‘)
        },
      };
      // debugger
      const copyed = JSON.parse(JSON.stringify(test));
      test.name = ‘test‘
      console.error(‘ddd‘, test, copyed)
技術分享圖片 image.png 技術分享圖片 image.png

4、如果obj裏有NaN、Infinity和-Infinity,則序列化的結果會變成null


技術分享圖片 image.png

5、JSON.stringify()只能序列化對象的可枚舉的自有屬性,例如 如果obj中的對象是有構造函數生成的, 則使用JSON.parse(JSON.stringify(obj))深拷貝後,會丟棄對象的constructor;

      function Person(name) {
        this.name = name;
        console.log(name)
      }

      const liai = new Person(‘liai‘);

      const test = {
        name: ‘a‘,
        date: liai,
      };
      // debugger
      const copyed = JSON.parse(JSON.stringify(test));
      test.name = ‘test‘
      console.error(‘ddd‘, test, copyed)

技術分享圖片 image.png

6、如果對象中存在循環引用的情況也無法正確實現深拷貝;

以上,如果拷貝的對象不涉及上面講的情況,可以使用JSON.parse(JSON.stringify(obj))實現深拷貝,但是涉及到上面的情況,可以考慮使用如下方法實現深拷貝:

 function  deepClone(data) {
      const type = this.judgeType(data);
      let obj;
      if (type === ‘array‘) {
        obj = [];
      } else if (type === ‘object‘) {
        obj = {};
      } else {
    // 不再具有下一層次
        return data;
      }
      if (type === ‘array‘) {
        // eslint-disable-next-line
        for (let i = 0, len = data.length; i < len; i++) {
          obj.push(this.deepClone(data[i]));
        }
      } else if (type === ‘object‘) {
        // 對原型上的方法也拷貝了....
        // eslint-disable-next-line
        for (const key in data) {
          obj[key] = this.deepClone(data[key]);
        }
      }
      return obj;
    },


function  judgeType(obj) {
  // tostring會返回對應不同的標簽的構造函數
      const toString = Object.prototype.toString;
      const map = {
        ‘[object Boolean]‘: ‘boolean‘,
        ‘[object Number]‘: ‘number‘,
        ‘[object String]‘: ‘string‘,
        ‘[object Function]‘: ‘function‘,
        ‘[object Array]‘: ‘array‘,
        ‘[object Date]‘: ‘date‘,
        ‘[object RegExp]‘: ‘regExp‘,
        ‘[object Undefined]‘: ‘undefined‘,
        ‘[object Null]‘: ‘null‘,
        ‘[object Object]‘: ‘object‘,
      };
      if (obj instanceof Element) {
        return ‘element‘;
      }
      return map[toString.call(obj)];
    },



JSON.parse(JSON.stringify()) 實現對對象的深拷貝