简体   繁体   English

javascript delete object属性正在删除整个对象

[英]javascript delete object property is deleting entire object

I have a bizarre issue happening here. 我在这里发生一个奇怪的问题。 I am retrieving data from a remote source and I need to reformat it for better internal use 我正在从远程源检索数据,我需要对其重新格式化以更好地内部使用

The data structure is like the following: 数据结构如下:

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: {...}
     ...
     ... 

I am looping through clubs and I want to assign the values of each club into its own events as property clubInfo . 我正在循环浏览各个俱乐部,并希望将每个俱乐部的值分配给它自己的events作为属性clubInfo When I do that though, clubInfo becomes and endless chain of itself. 但是,当我这样做时,clubInfo就会变成无止境的自身链条。 So I delete the new clubInfo.events - and then everything but the root club[0] gets wiped out. 因此,我删除了新的clubInfo.events ,然后clubInfo.events了除根club [0]之外的所有内容。 I hope I am being clear, its hard to explain. 我希望我很清楚,很难解释。

If I do this: 如果我这样做:

  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++) {
    }
  }

Then clubs becomes: 然后俱乐部变成:

   clubs [
       0: events [
           clubInfo [
               0: events [
                   clubInfo [
                       0: events [
                          ....and goes on seemingly forever
                          ]
                       ]
                   ]
               ]   
            ]
        ]

If I do: 如果我做:

  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
    }
  }

Then all that remains of clubs is, in fact none of the other properties that have arrays events or others (several of them) are all gone.: 那么,俱乐部剩下的所有东西,实际上没有其他具有数组events属性或其他(其中的一些)属性都没有消失。

   clubs [
       0: { 
          propA: "blah",
          probB: "bar"
          }
       ]

Instead of delete, i have even tried just nulling clubInfo.events = null - but the same issue happens, everything gets wiped out. 我什至没有尝试删除clubInfo.events = null而不是删除clubInfo.events = null但发生相同的问题,一切都消失了。

Oh boy, you've snagged one of JavaScript's current, and most obvious flaws by effectively using this: 哦,天哪,您已经有效地使用了JavaScript,这是JavaScript当前最明显的缺陷之一:

 clubs[i].event[j].clubInfo = clubs[i];

You're creating an infinite reference - what do I mean by that? 您正在创建一个无限引用 -这是什么意思? It's better displayed through an Array, if you'll oblige me: 如果您愿意的话,最好通过数组显示:

let a=[]; a.push([a]);

This creates an infinite level array through self-reference, creating an incalculable depth. 这通过自我引用创建了一个无限级数组,从而创建了无法计算的深度。 You see, though there's a 32(2^32-1) bit limit to an Array's length. 您会看到,尽管数组的长度有32(2 ^ 32-1)位的限制。 This can be demonstrated easily: 这很容易证明:

 Array(2**32); //Uncaught RangeError: Invalid array length

Presumably this was done to prevent browser memory from shorting but, strangely, there was never any consideration to the depth an array may contain. 大概这样做是为了防止浏览器内存不足,但是奇怪的是,从来没有考虑过数组可能包含的深度。 A minor side effect of this is that there is no depth property, but a major side effect is that there is no protection from an infinite self-referencing array . 这样做的一个小的副作用是没有depth属性,但是一个主要的副作用是没有针对无限的自引用数组的保护

Getting Around It 绕过它

The best way to get around this type of situation is to construct a new Object and assign properties from the old Object to the new. 解决这种情况的最佳方法是构造一个新的Object并将属性从旧的Object分配给新的Object。 You can think of this as cloning . 您可以将其视为克隆 To do this you can utilize the assign method: 为此,您可以利用assign方法:

Object.assign(constructor, **Array**/**Object**)

Example: 例:

let a = []; a.push(Object.assign([], a)); 

Problem solved, right? 问题解决了吧? uhhh... not quite Even though this can sometimes work, this still won't fix the issue of an Array or Object with more than shallow references. 唔......不太即使这样有时会工作,这仍然没有解决一个数组的问题,或者与比浅引用多个对象。 To get around that you have to use a combination of: 要解决这个问题,您必须使用以下组合:

  JSON.stringify(obj);

to break references 破坏参考

  JSON.parse(JSON);

to remake your object , and 重新制作您的对象 ,以及

  delete obj[deepReference];

deletion to stop any unforeseen issues with any superfluous data/references 删除以停止任何多余的数据/引用的意外问题

None of this is ideal, but currently there is no way to completely separate all references inside of an object or array without recursive iteration. 所有这些都不是理想的,但是当前没有办法在没有递归迭代的情况下完全分离对象或数组内的所有引用。

To give you an example - In your case you're going to want to do something like this: 举一个例子- 在您的情况下,您将要执行以下操作:

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

Additional Info: Other watch outs 附加信息:其他注意事项

Similarly there are other issues in the language. 同样,该语言还存在其他问题。 A badly implemented Array constructor method. 一个不好实现的Array构造函数方法。 Array(n) returns an Array with n members. Array(n)返回具有n成员的Array。 Why's that an issue? 为什么这是个问题? Everything in JavaScript that is declared and not instantiated is undefined except the members of a freshly constructed array. 除了新构造的数组的成员之外,JavaScript中声明和未实例化的所有内容均未undefined They return empty . 他们返回空了 The issue with that is this means they have no mappable values. 问题在于这意味着它们没有可映射的值。 Ergo, all those sweet new functional ES Array methods are useless until the Array is filled. 如此,所有这些不错的新功能性ES Array方法在数组被填充之前都是无用的。 As an example: 举个例子:

Array(3).map((m, i) => i);

This results in well... the same thing you started with — when clearly it should provide a numbered array from 0-2. 这样做的结果是...与您刚开始的事情一样—显然,它应该提供从0-2的编号数组。 This is not as big of a deal as an infinite reference because you can work around it like this: 无限引用相比,这没什么大不了的,因为您可以像这样解决它:

Array(3).fill(0).map((m,i) => i);

But it's effectively a wasted method call to take care of a problem that should be handled within construction. 但这实际上是浪费的方法调用,以解决应在构造内处理的问题。

Lastly, the fill method — give it an object or an Array and it doesn't create n individual object members. 最后, fill方法-给它一个对象或一个数组,它不会创建n单独的对象成员。 It creates n references to a singular array or object and stuffs them into one array. 它创建对单个数组或对象的 n 引用 ,并将它们填充到一个数组中。 At base logic, it sort of makes sense. 在基本逻辑上,这很有道理。 As @FelixKling pointed out in the comments, it is fairly consistent with what you would expect, ae fill this array with this one thing. 作为@FelixKling在评论中指出,这你所期望的相当一致,AE 填补这一阵列与这样 一两 件事。 I still would debate a bit about it's functionality for two reasons. 由于两个原因,我仍然会对其功能进行一些辩论。

  1. In what situation would anyone need n references stored in an Array to the same place in memory? 在什么情况下,任何人都需要将n引用存储在数组中到内存中的相同位置? Probably never . 可能永远不会 How often do people need an Array of similarly constructed Objects? 人们多久需要一次类似构造的对象阵列? All the time . 一直

  2. When passing an Object Literal for instance ( .fill({a:1}) )I can see the logic of filling the Array with references, even if it may not be wholly intuitive. 例如,当传递对象文字( .fill({a:1}) )时,我可以看到用引用填充数组的逻辑,即使它可能不是很直观。 If passed a Constructor- I would contest that it might make more sense to instantiate each member individually. 如果通过了构造函数,我会争辩说,单独实例化每个成员可能更有意义。

So there are many nuances, and inconsistencies with JavaScript that require knowledge to work around — and sadly, infinite reference , is one of them - but on the plus side the only way to typically realize these issues exist is to run into them headlong, so be thankful it wasn't in production! 因此,存在许多细微差别,并且与JavaScript的不一致需要知识来解决-并且可悲的是, 无限引用是其中之一-但是从好的方面来说,通常要意识到这些问题的唯一出路便是陷入困境,因此值得庆幸的是它不在生产中!

Hope this helps! 希望这可以帮助! Happy Coding! 编码愉快!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM