Map the Debris: FCC solution 3. An array copy with JSON

hello,
Map the Debris
In FCC solution 3:

function orbitalPeriod(arr) {
  var GM = 398600.4418;
  var earthRadius = 6367.4447;
  // Create new array to prevent modification of the original
  var newArr = JSON.parse(JSON.stringify(arr));
  // Loop through each item in the array arr
  newArr.forEach(function(item) {
    // Calculate the Orbital period value
    var tmp = Math.round(
      2 * Math.PI * Math.sqrt(Math.pow(earthRadius + item.avgAlt, 3) / GM)
    );
    //Delete the avgAlt property
    delete item.avgAlt;
    //Add orbitalPeriod property
    item.orbitalPeriod = tmp;
  });
  return newArr;
}

// test here
orbitalPeriod([{ name: "sputnik", avgAlt: 35873.5553 }]);

Why do you made the arr’s copy transforming JS to JSON then JSON to JS ? :

var newArr = JSON.parse(JSON.stringify(arr));

I would have used:

let newArr = [...arr]

There is a difference. This:

let newArr = [...arr]

will create a shallow array. In other words, if they are primitives, it will make new copies of them, but if they are reference types, then you are just copying the address (reference) so it will still point to the same place in memory:

const arr1 = [{data: 'hi'}]
const arr2 = [...arr1]

arr1[0].data = 'howdy'

console.log(arr1[0].data)
// howdy

console.log(arr2[0].data)
// howdy

If you want those to change too, you have to do a deep clone, or at least deep enough to get what you want.

One easy way to get a deep clone of a JS data structure, is to use the JSON trick. This will work as long as the JS data is in a form that can be converted to JSON, (e.g., doesn’t have functions/methods, no circular references, etc.)

The idea of “copying data” is not so simple in JS, especially with reference types.

So:

If I have a table with strings, numbers, booleans, null, undefined, or symbols I can make a copie with […arr] which is a spread if I don’t make a mistake.

If I have a table with some objects inside, I have to use the JSON trick.

Correct ?

We never seen that before or I have forgotten ?

Yes, those are primitive sites so there is no reference to copy - it is the actual value that will be passed.

If I have a table with some objects inside, I have to use the JSON trick.

No, that is one way to solve the problem. You can write a recursive algorithm to deep clone the value. I’m sure you can find many examples online. Lodash also has the cloneDeep method. Also keep in mind that the JSON trick won’t work if there are functions, regular expressions, undefined, NaN, etc. JSON can only handle a subset of JS data. True, a mostly useful subset, but a subset nonetheless.

And you may have a more complicated situation where you want specific considerations. Maybe you want everything copied but you want functions to retain the same reference, so you don’t make extra copies. Maybe you only want certain objects copied. You may have to write a custom clone function.

We never seen that before or I have forgotten ?

I don’t know, it could be either. Don’t worry about it too much. Learning coding is messy. There is a lot of interrelated info and some irreducible complexity. Just keep learning.

This sort of thing is another reason why I like inherently non-mutating approaches, like using a map.

1 Like