That's an excellent and very opinionated question.
I personally don't like to have entire script wrapped in load event. It adds extra indentation. I prefer to silently assume that the script is running when the DOM is ready.
In the past I used to prefer putting
<script> just before closing the
</body>. But now, as we have
defer attributes of the
<script>, I feel like they are the best. Most of the time I end up having my script in
<head> and with
<script src="foo.js" defer></script>
This way, script runs when the DOM is ready, but it starts downloading sooner. If your page has a lot of content in the source, it actually makes quite a difference in terms of performance.
And if my script doesn't need DOM,
async is a better choice, because it runs as soon as it's downloaded, but also doesn't block rendering of the DOM when it's being downloaded.