You don't have to, but there are edge-cases, which might cause trouble if not properly separated by a semicolon (even with newlines!). You could instead set up linting, like eslint, to know about such instances, and linting is always good for consistent code and standards, however just putting semicolons is way easier and you don't have to put wild semicolons in places ;)
One problem case is:
const foo = 42
[1,2,3].forEach(i => console.log(i))
What output do you expect? 1 2 3? Well, nope. You will get the following:
Uncaught TypeError: Cannot read property 'forEach' of undefined
Because even with the newlines, the JS VM will think that you wanted to access the field called 3 (because comma can also be used as an operator for execution separation, and will yield the result of the last operand, which is 3 in this case) on the number object 42 and call the function forEach on it, which is impossible, since there is no field called 3 on 42.
Basically, your JS VM reads above code like this:
const foo = 42[3].forEach(i => console.log(i))
Edit:
Imagine you do have an element with field 3 and above code does not throw, however your logic does not do what you want and you just sit there and think everything looks fine? Even if you debug the code line-by-line, you might wonder how tf the value suddenly changed in that strange way from one line to the next. Semicolons might be seen as tedious, however I think, in JS, they are necessary. Also, other languages require them always, so if you make it a habit to put semicolons, you will have an easier life with other languages, should you decide to learn one with semicolons (Java, Rust, C, C++, C#,...)