This. A thousand times, this. It's a really good model for something that is I/O bound because it is easy to reason about. This makes the model perfect for events in the browser (both DOM events and XHR).
It's not that Javascript is especially suited to this model, but thanks to the browser, it was already the most used implementation of this model.
I think this combined with the fact that JS engines were already relatively isolated from the browser itself and able to be embedded with other software (in the case of node.js libuv/libev) made it a really good option. require+npm added a lot more to the mix.
But it was the broad availability of mindshare of those developers who at least knew some JS that really kicked it over the top, given JS as a DSL for I/O bound applications.
It's not that Javascript is especially suited to this model, but thanks to the browser, it was already the most used implementation of this model.