I believe this ends in semantics.
window.onload = () => {
tabButtons[0].onclick = openCity(e, "London");
tabButtons[0].onclick = openCity(e, "York");
tabButtons[0].onclick = openCity(e, "Ontario");
}
<div class="tab">
<button class="tablinks" onclick="openCity(event, 'London')">London</button>
<button class="tablinks" onclick="openCity(event, 'Paris')">Paris</button>
<button class="tablinks" onclick="openCity(event, 'Tokyo')">Tokyo</button>
</div>
My example in the previous post requires cleverness to open the correct tab making the code more complex. Or removing the for each and manually creating three events. In-which case future improvements require changing each-line regardless if it's in html or js. For tabs I see the javascript version as unnecessary extra code and complexity. I look at tabs and I know what the code is going to be. It doesn't effect me from a coder perspective if it's in html or JS.
"should be separate from html & really bad practice." This is not the case. I agree code is cleaner, easier to read, and it's best practice. However, just like 'goto' has legitimate situations for its use so does inline-events. Not every use results in hundreds of instances. This isn't a massive database. It's a tab menu and whichever method a person decides to implement will likely be straight forward.
The global event object can be avoided instead using the addEventHandler being a proper solution