Your intuition is correct.
Let’s break it down.
const coinArray = ["Heads", "Tails"];
Self explanatory really, it’s an array definition.
computerToss = Math.floor(Math.random() * coinArray.length);
Now you say this will be either 0 or 1. Is that strictly true in all cases? No. It is in your specific execution, but it wont be true in general.
Why? Let’s look closer.
Math.random() is a defined function that will return a value in the range [0,1). So it will never be 1, but it will be 0.999999 etc.
coinArray.length is currently 2. But you could put any array into coinArray. What if i made it a 6-sided die? “coinArray” could be [1,2,3,4,5,6] , or [“Heads”,“Tails”,“Side”] (because it is theoretically possible with certain coins to land a flip on the edge). So the length is some integer greater than or equal to 0. Let us assume for the moment that you don’t leave the array empty (because that ends in your code exploding).
So we have a number in the range [0,1), multiplied by a positive integer (which i will call X). Mathematics tell us that this will result in a number in the range [0,X) . Note that we can never get to X, because we can never get a 1 out of Math.random().
We then take the floor of that number. So we drop all the decimal places and keep the whole number. This actually means our number is in the set [0,…,X-1]. (again, we could never get to X, but the floor of (X-1).99999999 is still X-1.)
[0,…,X-1] is also the range of references that are valid for a 0-indexed array with length X.
So we can say
coinArray[computerGuess] and know that it’s a valid array reference.
Let’s take the specific example here. We have a length of the array, X = 2.
Math.random always generates a number between 0 and 0.99999999…
2* the number math.random generates will be between 0 and 1.99999999…
flooring that number will result in either a 0 or a 1.
if it floored to a 0, then we say “Heads” (because coinArray = “Heads”)
if it floored to a 1, then we say “Tails” (because coinArray = “Tails”)