JSON.parse(JSON.stringify()) 實現對對象的深拷貝
阿新 • • 發佈:2019-03-23
title pan ttr ror i++ 得到 epc 將不 ins
為
1、如果obj裏面有時間對象,則JSON.stringify後再JSON.parse的結果,時間將只是字符串的形式。而不是時間對象;
image.png
JSON.parse(JSON.stringify(obj))
我們一般用來深拷貝,其過程說白了 就是利用JSON.stringify 將js對象序列化(JSON字符串),再使用JSON.parse來反序列化(還原)js對象;序列化的作用是存儲(對象本身存儲的只是一個地址映射,如果斷電,對象將不復存在,因此需將對象的內容轉換成字符串的形式再保存在磁盤上 )和傳輸(例如 如果請求的Content-Type
是 application/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()) 實現對對象的深拷貝