1

I have been experimenting with the const keyword in JavaScript as I learn it. I realized that I can add items to an object or an array.

For arrays, when I add to an index that isn't right after the end, I end up with empty items. When I log one of the values it is says undefined. How can I get the log display to show undefined.

const arr = [0, 1];
console.log('Expect: [0, 1] Result = ', arr);
arr[1] = 'a';
console.log('Expect: [0, \'a\'] Result = ', arr);
arr[2] = 'c';
console.log('Expect: [0, \'a\', \'c\'] Result = ', arr);
arr[8] = 3;
console.log(arr);
console.log('Expect: [0, \'a\', <5 empty items>, 3] Result = ', arr);

console.log(arr[7]);

For node, the last two lines give:

Expect: [0, 'a', <5 empty items>, 3] Result =  [ 0, 'a', 'c', <5 empty items>, 3 ]
undefined

How could I get the log to look like:

[0, 'a', undefined, undefined, undefined, undefined, undefined, 3]

EDIT
Note that I am not trying to replace the values with say zero. I just want to see the array with the values it contains, just like how the other elements show up.

I tried the Chrome console and it also shows empty but empty × 5 rather than <5 empty items>.

Expect: [0, 'a', <5 empty items>, 3] Result =  (9) [0, "a", "c", empty × 5, 3]
heretoinfinity
  • 1,528
  • 3
  • 14
  • 33
  • 1
    You can use fill: arr.fill(undefined, 3, 8); – Maciej Kasprzak May 27 '20 at 10:59
  • @PeterSeliger Why would anything in this script give a different console output in node than in a browser? – mplungjan May 27 '20 at 11:01
  • you may use spread syntax, like `x = ['a','b','c',,,]; y = [...x]; console.log(y)` would return `["a", "b", "c", undefined, undefined, undefined]` – Yevhen Horbunkov May 27 '20 at 11:01
  • Does this answer your question? [replacing empty with zero values in array](https://stackoverflow.com/questions/51259553/replacing-empty-with-zero-values-in-array) – Yannick K May 27 '20 at 11:04
  • @YannickK, I am not trying to replace values, just show them as they are. – heretoinfinity May 27 '20 at 11:14
  • 1
    Node doesn't treat `empty items` as `undefined` necessarily though, so I'd say your best bet is to just replace all of them with undefined. – Yannick K May 27 '20 at 11:18
  • @MaciejKasprzak, is this quirkiness just in javascript where I have to refill the exact same values to the elements to have them displayed as they truly are? – heretoinfinity May 27 '20 at 11:18
  • @YannickK, how are they treated as? I will add output from the browser console, which is similar. – heretoinfinity May 27 '20 at 11:20
  • 1
    Empty items are seen as non-existing, which is why if you `map()` over your array it skips the empty items, as opposed to undefined which it wouldn't skip over. – Yannick K May 27 '20 at 11:22

1 Answers1

1

The reason for this behaviour is that Node treats holes and undefined elements differently:

Try this in node:

let a = []
a[0] = undefined
a[4] = 'foo'
console.log(a)
// You will see: [ undefined, <3 empty items>, 'foo' ]

The reasons for this are known to the creators of Node's V8 engine, who I am sure have great reasons for it. However, if you really want to see undefined where node sees empty for all arrays, you can introduce a new function to the array object as such:

Array.prototype.toPrettyString = function() {
    for (let i = 0; i < this.length; i++) {
        if (this[i] === undefined) this[i] = undefined;
    }
    return this;
}

// Now, when you construct new Arrays:

let a = []
a[0] = undefined
a[4] = 'foo'
console.log(a)
// You will see: [ undefined, undefined, undefined, undefined, 'foo' ]

However, this has its own pitfalls and you should read this answer: JavaScript: What dangers are in extending Array.prototype? if you decide to go down this road.

Additional Details

The behaviour will be different across browsers and node because they each implement their own JavaScript interpreters (chrome & node use v8 https://v8.dev/ but obviously have differences due to node being designed as a server side language and chrome being client side)

As an addendum, this behaviour is rarely encountered in the wild as most production grade js don't really leave holes in arrays. To see why it can be dangerous to rely on this:

let a = [];
a[0] = undefined;
a[4] = 'foo';

let count = 0;
for(i of a) { count++ }
console.log(count)
// You will see 5

count = 0; 
a.forEach(a => count += 1)
console.log(count)
// You will see 2. not 5!

I.e. the semantics of for .. of is different from .forEach when it comes to holes!

Swayam
  • 580
  • 6
  • 11