想請問各位大大,在編輯json時會使用JSON.stringify()及JSON.parse() 將字串轉物件或事物漸轉字串進行操作,爬文後有人解說原因:透過先將物件轉成字串,再轉回物件,將傳參考的特性完全消滅。
JSON.parse(JSON.stringify(obj))
但是為甚麼透過這樣的轉換就能對一個物件進行深複製??
希望有大大可以替小弟解惑
深複製還是要用一點手段,我都不敢保證JSON.stringify不會弄丟資料
var a = { a: '1' };
console.log(a)
var b = deepClone(a);
console.log(b);
a.a = "2";
console.log(a);
console.log(b);
function deepClone(obj) {
/*
* Duplicates an object
*/
var ret = null;
if (obj !== Object(obj)) { // primitive types
return obj;
}
if (obj instanceof String || obj instanceof Number || obj instanceof Boolean) { // string objecs
ret = obj; // for ex: obj = new String("Spidergap")
} else if (obj instanceof Date) { // date
ret = new obj.constructor();
} else
ret = Object.create(obj.constructor.prototype);
var prop = null;
var allProps = Object.getOwnPropertyNames(obj); //gets non enumerables also
var props = {};
for (var i in allProps) {
prop = allProps[i];
props[prop] = false;
}
for (i in obj) {
props[i] = i;
}
//now props contain both enums and non enums
var propDescriptor = null;
var newPropVal = null; // value of the property in new object
for (i in props) {
prop = obj[i];
propDescriptor = Object.getOwnPropertyDescriptor(obj, i);
if (Array.isArray(prop)) { //not backward compatible
prop = prop.slice(); // to copy the array
} else
if (prop instanceof Date == true) {
prop = new prop.constructor();
} else
if (prop instanceof Object == true) {
if (prop instanceof Function == true) { // function
if (!Function.prototype.clone) {
Function.prototype.clone = function() {
var that = this;
var temp = function tmp() {
return that.apply(this, arguments);
};
for (var ky in this) {
temp[ky] = this[ky];
}
return temp;
}
}
prop = prop.clone();
} else // normal object
{
prop = deepClone(prop);
}
}
newPropVal = {
value: prop
};
if (propDescriptor) {
/*
* If property descriptors are there, they must be copied
*/
newPropVal.enumerable = propDescriptor.enumerable;
newPropVal.writable = propDescriptor.writable;
}
if (!ret.hasOwnProperty(i)) // when String or other predefined objects
Object.defineProperty(ret, i, newPropVal); // non enumerable
}
return ret;
}
謝謝大大提供的方法~
想請問只要是重新解析的物件,就會新增一個記憶體位置,不知這樣的理解是不是對的?
用C++的角度來看,是產生一個新指標,然後把裡面的東西全部遞迴複製一遍
下面表演一下JSON.Stringify是如何弄丟東西的
要用到我提供的deepClone哦!
var a = {
a: '1',
firstName: 'xxxxx',
lastName: '00000',
fullName: function() {
return this.firstName + " " + this.lastName;
}
};
console.log(a.fullName());
var b = deepClone(a);
var c = JSON.parse(JSON.stringify(a));
console.log(b.fullName());
console.log(c.fullName());
debug結果
你還敢JSON.Stringify ?
放在jsfiddle裡給大家玩
https://jsfiddle.net/japhenchen/Lc6z7fp4/3/
結論就是 fullName:function() 不會被JSONStringify到 c 去...
...放function就不是JSON了,只是javascript object而已。
JSON是交換格式,並沒有放function的格式。
題目是
JSON.parse(JSON.stringify(obj))
obj也不是JSON
JSON.stringify是個交換資料的好方法,但不能當做是"深層拷貝"的方法,樓主的意思是要把object複製到另一個
可以把JSON.Stringify看成是影印機,可以複印一份身份証,但卻不能當做正本使用