2) The language -- Javascript has relatively few convenience features in the standard library (at least compared to ruby, which is my point of reference) so more of those features are implemented in userland (and thus imported from npm). I think this is the biggest cause of massive dependency trees -- things like left_pad simply exist natively in many other languages.
3) The ecosystem -- for whatever reason, installing floating package versions was the default for a long time; floating package versions are obviously an order of magnitude more vulnerable to an attacker publishing a malicious update.
Edit: 4) I think it's also probably true that Javascript apps are particularly susceptible to this class of vulnerability, but that doesn't necessarily mean they're less secure overall. Javascript teams tend to move quickly and stay on the cutting edge, so they install lots of packages/updates and are thus vulnerable to malicious updates. Equifax's Java app was compromised for exactly the opposite reason -- they didn't install a security update to Apache Struts for months. That class of vulnerability is far less likely to happen on a fast-moving Javascript app. It's all a tradeoff; the important takeaway is to understand the failure modes for your particular stack and be vigilant against them (which in this case means using a lockfile and doing your best to audit new packages/updates).
[1] https://insights.stackoverflow.com/survey/2018#most-popular-...