Three copies of the truth
state has no home
The server knows, a variable knows, and the DOM knows, and nothing keeps the three agreeing. Half of every bug report is two of them disagreeing, and reproducing it means retracing the exact click order that pulled them apart.
if ($('#row-3').hasClass('done')) …
// asking the page what it thinks it knowsYou write the steps, not the result
every transition by hand
The code says how to get from this state to that one, so every pair of states needs its own patch. Add a fourth field to a form and you are not writing one branch — you are writing it against every state the form was already in.
if (n === 0) el.classList.add('empty')
else el.classList.remove('empty')Nothing is a unit
there is no component to reuse
A widget is markup in one file, a rule in a stylesheet and a handler in a script, joined only by an id string. Put two on a page and the ids collide, the styles leak into each other, and neither one moves without finding all three pieces.
<div id="cart-count"> <!-- html -->
#cart-count { … } /* css */
$('#cart-count') // jsThe page or the app
you get one of the two
Full reloads are simple and lose everything — scroll, focus, half-typed input. Not reloading keeps them, but then routing, history, the back button and the title bar all become code you write, and get subtly wrong.
location.href = '/cart'
// simple, and the scroll position is gone