Memory and storage
A page's variables live in memory and vanish when the page closes or reloads. Web storage keeps small pieces of text in the browser itself. localStorage holds key-value pairs for each website and survives reloads and restarts.
The first visit
The page has a paragraph that says "Hello!" and a script tag. The browser draws the page, then hands visits.js to the JavaScript engine, which runs it top to bottom. The page's memory starts empty.
getItem("visits") asks localStorage for the value under the key "visits". This is the first visit, so there is no such key, and getItem returns null, which means "no value". So saved is null.
Number(saved) turns the stored value into a number. Number(null) is 0, so visits is 0 + 1 = 1. It is a number, kept in the page's memory like any other variable.
setItem("visits", visits) saves the pair in localStorage. Storage keeps only strings, so the number 1 is stored as the text "1". It now lives in the browser, outside the page's memory.
Line 4 finds the paragraph with the id msg. Line 5 sets its text, and the browser redraws it: the page now says "Visit number 1".
Reload and come back
You reload the page. The browser throws the old page away with its memory: saved and visits are gone. localStorage is kept, so "visits" still holds "1". The script runs again from line 1.
This time getItem finds the key and returns "1". It comes back as a string, the same text that was stored, so saved is the string "1", not the number 1.
Number("1") is 1, plus 1 makes 2. Without Number, "1" + 1 would join two pieces of text and give "11". Turn a stored value back into a number before doing maths with it.
setItem replaces the old value: "visits" now holds "2". Lines 4 and 5 make the page say "Visit number 2". Each reload adds one, until the site's data is cleared.
The rules
Each origin, meaning scheme, host and port such as http://localhost:8000, gets its own store; other sites cannot read it. sessionStorage works the same way but is cleared when the tab closes. To store an object, save JSON.stringify(obj) and read it with JSON.parse.
What happens
// step 1/11 · storage
memory variables: gone on reload
localStorage key-value pairs, all strings
one store per origin
kept after reloads and restarts
sessionStorage the same, cleared when the tab closes
The Web Storage API keeps every key and value as a string. setItem converts what you pass to a string, so the number 1 is stored as "1", and an object would be stored as the useless text "[object Object]" unless you JSON.stringify it first. The memory boxes are a simplification: saved and visits are bindings in the script's scope. When the page is reloaded, a fresh script runs with fresh bindings; nothing from the old page's memory survives.