[英]javascript delete object property is deleting entire object
我在這里發生一個奇怪的問題。 我正在從遠程源檢索數據,我需要對其重新格式化以更好地內部使用
數據結構如下:
clubs = [
0: {
propA: "blah",
probB: "bar",
events: [
0: {
data1: "foo",
data2: "bar"
}
1: {
data1: "this",
data2: "that"
}
1: {
propA: "hello",
probB: "bye",
events [
0: { ...}
1: {...}
...
...
我正在循環瀏覽各個俱樂部,並希望將每個俱樂部的值分配給它自己的events
作為屬性clubInfo
。 但是,當我這樣做時,clubInfo就會變成無止境的自身鏈條。 因此,我刪除了新的clubInfo.events
,然后clubInfo.events
了除根club [0]之外的所有內容。 我希望我很清楚,很難解釋。
如果我這樣做:
for (var i=0; i<clubs.clubs.length;i++) {
var clubInfo = clubs.clubs[i] ;
var events = clubs.clubs[i].events ;
for (var j=0; j<events.length; j++) {
}
}
然后俱樂部變成:
clubs [
0: events [
clubInfo [
0: events [
clubInfo [
0: events [
....and goes on seemingly forever
]
]
]
]
]
]
如果我做:
for (var i=0; i<clubs.clubs.length;i++) {
var clubInfo = clubs.clubs[i] ;
delete clubInfo.events ;
var events = clubs.clubs[i].events ; // events is now empty
for (var j=0; j<events.length; j++) { // errors here because there is no length after the delete
}
}
那么,俱樂部剩下的所有東西,實際上沒有其他具有數組events
屬性或其他(其中的一些)屬性都沒有消失。
clubs [
0: {
propA: "blah",
probB: "bar"
}
]
我什至沒有嘗試刪除clubInfo.events = null
而不是刪除clubInfo.events = null
但發生相同的問題,一切都消失了。
哦,天哪,您已經有效地使用了JavaScript,這是JavaScript當前最明顯的缺陷之一:
clubs[i].event[j].clubInfo = clubs[i];
您正在創建一個無限引用 -這是什么意思? 如果您願意的話,最好通過數組顯示:
let a=[]; a.push([a]);
這通過自我引用創建了一個無限級數組,從而創建了無法計算的深度。 您會看到,盡管數組的長度有32(2 ^ 32-1)位的限制。 這很容易證明:
Array(2**32); //Uncaught RangeError: Invalid array length
大概這樣做是為了防止瀏覽器內存不足,但是奇怪的是,從來沒有考慮過數組可能包含的深度。 這樣做的一個小的副作用是沒有depth
屬性,但是一個主要的副作用是沒有針對無限的自引用數組的保護 。
繞過它
解決這種情況的最佳方法是構造一個新的Object並將屬性從舊的Object分配給新的Object。 您可以將其視為克隆 。 為此,您可以利用assign
方法:
Object.assign(constructor, **Array**/**Object**)
例:
let a = []; a.push(Object.assign([], a));
問題解決了吧? 唔......不太即使這樣有時會工作,這仍然沒有解決一個數組的問題,或者與比淺引用多個對象。 要解決這個問題,您必須使用以下組合:
JSON.stringify(obj);
破壞參考
JSON.parse(JSON);
重新制作您的對象 ,以及
delete obj[deepReference];
刪除以停止任何多余的數據/引用的意外問題
所有這些都不是理想的,但是當前沒有辦法在沒有遞歸迭代的情況下完全分離對象或數組內的所有引用。
舉一個例子- 在您的情況下,您將要執行以下操作:
for (var i = 0; i < clubs.length; i++) {
var clubInfo = clubs[i];
var events = clubs[i].events;
for (var j = 0; j < events.length; j++) {
let jsonTranslation = Object.assign({}, clubs[i]);
delete jsonTranslation.events;
jsonTranslation = JSON.stringify(jsonTranslation);
clubs[i].events[j].clubInfo = JSON.parse(jsonTranslation);
}
}
let clubs = [{ propA: "blah", probB: "bar", events: [{ data1: "foo", data2: "bar" }, { data1: "this", data2: "that" } ] }]; for (var i = 0; i < clubs.length; i++) { var clubInfo = clubs[i]; var events = clubs[i].events; for (var j = 0; j < events.length; j++) { let jsonTranslation = Object.assign({}, clubs[i]); delete jsonTranslation.events; jsonTranslation = JSON.stringify(jsonTranslation); clubs[i].events[j].clubInfo = JSON.parse(jsonTranslation); } } console.log(clubs);
附加信息:其他注意事項
同樣,該語言還存在其他問題。 一個不好實現的Array構造函數方法。 Array(n)
返回具有n
成員的Array。 為什么這是個問題? 除了新構造的數組的成員之外,JavaScript中聲明和未實例化的所有內容均未undefined
。 他們返回空了 。 問題在於這意味着它們沒有可映射的值。 如此,所有這些不錯的新功能性ES Array方法在數組被填充之前都是無用的。 舉個例子:
Array(3).map((m, i) => i);
這樣做的結果是...與您剛開始的事情一樣—顯然,它應該提供從0-2的編號數組。 與無限引用相比,這沒什么大不了的,因為您可以像這樣解決它:
Array(3).fill(0).map((m,i) => i);
但這實際上是浪費的方法調用,以解決應在構造內處理的問題。
最后, fill
方法-給它一個對象或一個數組,它不會創建n
單獨的對象成員。 它創建對單個數組或對象的 n
引用 ,並將它們填充到一個數組中。 在基本邏輯上,這很有道理。 作為@FelixKling在評論中指出,這是你所期望的相當一致,AE 填補這一陣列與這樣 一兩 件事。 由於兩個原因,我仍然會對其功能進行一些辯論。
在什么情況下,任何人都需要將n
引用存儲在數組中到內存中的相同位置? 可能永遠不會 。 人們多久需要一次類似構造的對象陣列? 一直 。
例如,當傳遞對象文字( .fill({a:1})
)時,我可以看到用引用填充數組的邏輯,即使它可能不是很直觀。 如果通過了構造函數,我會爭辯說,單獨實例化每個成員可能更有意義。
因此,存在許多細微差別,並且與JavaScript的不一致需要知識來解決-並且可悲的是, 無限引用是其中之一-但是從好的方面來說,通常要意識到這些問題的唯一出路便是陷入困境,因此值得慶幸的是它不在生產中!
希望這可以幫助! 編碼愉快!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.