1

I am trying to create an array which has a defined length and fill it with empty arrays. I've tried using all possibilities given by @stpoa's answer here but my array does not behave correctly.

Given the code (I simplified it for the sake of example):

const tasksArray = Array(3).fill([])
const tasksArray2 = [[], [], []]
const tasks = ['task1', 'task2']

const fillWithData = (array) => {
  tasks.forEach(task => {
    array[0].push(task)
  })
}

Gives me an incorrect output for tasksArray and a obviously a correct one for tasksArray2 which is hardcoded

fillWithData(tasksArray) // [['task1', 'task2'], ['task1', 'task2'], ['task1', 'task2']] => not OK, duplicates values!
fillWithData(tasksArray2) // [['task1', 'task2'], [], []] => that's OK
3

3 Answers 3

5

In taskArray, the [] you are using is passed as a reference, and the elements in taskArray all reference the same array.

In taskArray2, you have three separate empty arrays, [], each with their own reference. Therefore you do not get duplicated values.

If you wish to create an array of empty arrays programmatically, use Array.from -

const fillEmptyArrays = (count) =>
  Array.from(Array(count), _ => [])

const tasks =
  fillEmptyArrays(3)

console.log(tasks)
// [ [], [], [] ]

And please don't include type names like Array in your variable names tasksArray; just name it tasks. JavaScript is a dynamically-typed language and this kind of thinking hurts you in the long run.

Sign up to request clarification or add additional context in comments.

4 Comments

cool, I really love that. Could you only explain how _ can be understood?
Dandy, in this case _ is a convention that signals the function's parameter is not used in the function body and therefore doesn't need a name; the function always returns []. You could replace _ with any valid variable name and the program will still work. See Array.from's second argument for more details.
don't include type names like Array in your variable names ... this kind of thinking hurts you in the long run - What makes you think that?
@bob JavaScript bindings can have a value of any type, and in the case of let the type could change over time. Polymorphic functions... Dynamic function calls... there's nothing enforcing that someArray is an array, and in the dynamic cases when it's not an array, it's really hard on your brain to see "Array" in the name and then mentally treat it as something else.
4

You need to get independent object references inside of the array, instead of having literally the constant value.

By taking Array.from with an object with a length property and the build in mapping function, you could get an array of independent arrays.

const tasksArray = Array.from({ length: 3 }, _ => [])
const tasks = ['task1', 'task2']

const fillWithData = (array) => {
  tasks.forEach(task => {
    array[0].push(task)
  })
};

fillWithData(tasksArray);
console.log(tasksArray);

5 Comments

just use Array(3) - { length: 3 } is a voodoo and using this behavior directly keeps the programmer's mind at a level that is less effective.
@user633183, i like voodoo.
@user633183 I would disagree. Passing a super basic array-like should be not more voodoo than using a unary + or !! or other small tricks. I am fairly confident that at this point it's gaining traction to be an idiom like those, if it's not reached that point already.
Right, but as professional developers we also appreciate code that is straightforward, maintainable, and easy on our minds.
VLAZ, I strongly discourage + and !!. "Tricks are for kids!". Real programs demonstrate clear intentions. Use Number.parseInt and Boolean even if it's a few more keystrokes.
2

fill puts the value you pass it at each index of the array.

So tasksArray has three references to the same array, while tasksArray2 has a reference to each of three different arrays.

If you want to put three different arrays in there, then you need to explicitly create three arrays.

You could approach it with a counter:

const tasksArray2 = [];
let count = 3;
while (count--) {
    tasksArray2.push([]);
}

1 Comment

Thanks, now I understand that it was due to fill(). However, the Array.from() solution looks much cleaner.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.