JSON.stringify深拷貝的缺點


淺拷貝和深拷貝:

  • 針對對象
    深拷貝和淺拷貝只針對像Object和Array這樣的復雜對象的,String,Number等簡單類型不存在深拷貝。

淺拷貝:
因為淺拷貝只會將對象的各個屬性進行依次復制,並不會進行遞歸復制。在JavaScript中,對於Object和Array這類引用類型值,當從一個變量向另一個變量復制引用類型值時,這個值的副本其實是一個指針,兩個變量指向同一個堆對象,改變其中一個變量,另一個也會受到影響。所以淺拷貝會導致 obj.arr 和 shallowObj.arr 指向同一塊內存地址,當修改obj.arr的值時,shallowObj.arr的值同樣會被修改,

eg:
var a={a:1,b:2,c:3} var b=a b.a=2 console.log(a,b) 

深拷貝
而深拷貝則不同,它不僅將原對象的各個屬性逐個復制出去,而且將原對象各個屬性所包含的對象也依次采用深拷貝的方法遞歸復制到新對象上。這就不會存在上面 obj 和 shallowObj 的 arr 屬性指向同一個對象的問題。當修改obj.arr的值時,shallowObj.arr的值不會被修改,仍然為原值

eg:
function deepClone(obj){ let obj_ = JSON.stringify(obj), loneObj = JSON.parse(obj_); return loneObj } let a=[1,2,3,4], b=deepClone(a); b[0] = 2; console.log(a,b); 

弊端:
1.如果obj里面有時間對象,則JSON.stringify后再JSON.parse的結果,時間將只是字符串的形式,而不是對象的形式

eg:
var test = { name: 'a', date: [new Date(1536627600000), new Date(1540047600000)], }; let b; b = JSON.parse(JSON.stringify(test)); console.log(b); 

2.如果obj里有RegExp(正則表達式的縮寫)、Error對象,則序列化的結果將只得到空對象;

eg:
      const test = { name: 'a', date: new RegExp('\\w+'), }; // debugger const copyed = JSON.parse(JSON.stringify(test)); test.name = 'test' //console.error('ddd', test, copyed); console.log(copyed); 

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

eg:
  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); 

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

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

eg: 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) 

6、如果對象中存在循環引用的情況也無法正確實現深拷貝;
總結:
用法簡單,然而使用這種方法會有一些隱藏的坑:因為在序列化JavaScript對象時,所有函數和原型成員會被有意忽略。
通俗點說,JSON.parse(JSON.stringfy(X)),其中X只能是Number, String, Boolean, Array, 扁平對象,即那些能夠被 JSON 直接表示的數據結構。


JSON.stringify()的幾種妙用:

  • 判斷數組是否包含某對象,或者判斷對象是否相等。

    let data = [ {name:'echo'}, {name:'聽風是風'}, {name:'天子笑'}, ], val = {name:'天子笑'}; console.log(JSON.stringify(data).indexOf(JSON.stringify(val)) !== -1); console.log(data.indexOf(val) !== -1) //因為數組和對象是引用值不能比較,所以需要序列化一下轉成字符串 
  • 判斷兩數組/對象是否相等

    let a = [1,2,3], b = [1,2,3]; JSON.stringify(a) === JSON.stringify(b);//true 
  • 讓localStorage/sessionStorage可以存儲對象。
    localStorage/sessionStorage默認只能存儲字符串,而實際開發中,我們往往需要存儲的數據多為對象類型,那么這里我們就可以在存儲時利用json.stringify()將對象轉為字符串,而在取緩存時,只需配合json.parse()轉回對象即可。

    //存 function setLocalStorage(key,val){ window.localStorage.setItem(key,JSON.stringify(val)); }; //取 function getLocalStorage(key){ let val = JSON.parse(window.localStorage.getItem(key)); return val; }; //測試 setLocalStorage('demo',[1,2,3]); let a = getLocalStorage('demo');//[1,2,3] 

JSON.stringify()與toString()這兩者雖然都可以將目標值轉為字符串,但本質上還是有區別的,比如

let arr = [1,2,3]; console.log(JSON.stringify(arr));//'[1,2,3]' console.log(arr.toString());//1,2,3


作者:別鬧23
鏈接:https://www.jianshu.com/p/52db1d0c1780
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。


免責聲明!

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



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