0

I have the following function:

const arrayOfStrings = n => new Array(n)
    .fill(new Array(2 * n - 1).fill(' '))
    .map((e, i) => e
        .fill(i, i, e.length - i)
            .join(''));

I expect when invoked like this arrayOfStrings(3), I expect it to return the following:

[
    '00000',
    ' 111 ',
    '  2  '
]

However it doesn't, instead it returns this:

[
    '00000',
    '01110',
    '01210'
]

Or if I remove the .join('') from within the map and return e still as an array it returns this:

[
    [0,1,2,1,0],
    [0,1,2,1,0],
    [0,1,2,1,0]
]

What I believe is going on:

  • fill called inside map is running on every child array element in the mapped parent array on each iteration.
  • When join is present the the target child array (e) is returned as a string from each iteration, leaving one fewer arrays for the fill to be called on on the next iteration of map.
  • When join is absent the all three e elements remain arrays and fill is run on every child array on every iteration.

The Question

I'm not concerned particularly with how to get my desired outcome. What I want to know is why calling fill inside map behaves in this way?

Thanks

Josh
  • 1,517
  • 1
  • 13
  • 21
  • 1
    It's because in `.fill(new Array(2 * n - 1).fill(' '))` you're creating a **single** array filled with spaces and putting a reference to it in every slot in your outer array. So in the `map`, you first fill the entire array with `0`, then fill a subset of it with `1`, and then fill a smaller subset of it with `2`. You need *different* arrays. – T.J. Crowder Jun 08 '18 at 13:12
  • One common way is to use `Array.from`'s callback: `Array.from({length: n}, e => new Array(...))`. FWIW: http://jsbin.com/yewizuyuda/edit?html,js,output – T.J. Crowder Jun 08 '18 at 13:17
  • Ahh thank you! I understand now, so `fill` only evaluates the first argument once and that's why it's all the same array. Cheers! – Josh Jun 08 '18 at 13:42

0 Answers0