A page already has three cookies. What happens when script runs `document.cookie = "theme=dark; path=/; max-age=3600"`, and which parts of that string can ever be read back?
answer
- writes one cookie, not the whole string
- other cookies survive untouched
- attributes are write-only
- omitting path is not site-wide
- no exception when the write is rejected
basics
~20 sAssigning to document.cookie adds or replaces exactly one cookie and leaves the other three untouched — it is not a normal property assignment. Only the name=value part is ever readable afterwards; path and max-age are write-only.
solid answer
~50 sThe setter is not a normal assignment: it parses the string as a single `Set-Cookie`-style directive and applies it to the store. So this writes or overwrites the cookie named `theme` and leaves the other three exactly as they were — there is no way to clear the jar by assigning an empty string. Everything after the first `;` is attributes for that one cookie: `path=/` scopes it, `max-age=3600` makes it persist an hour instead of dying with the session. You can also set `domain`, `expires`, `secure`, `samesite` and `partitioned` here. Reading `document.cookie` afterwards returns only `theme=dark` among the pairs — the attributes never come back. And the write is silent: an over-long value, a disallowed attribute, or a cookie count over the browser's per-domain cap is simply dropped, with no exception and no return value to check.
code
javascript · 11 lines// Before: "a=1; b=2; c=3"
document.cookie = 'theme=dark; path=/; max-age=3600';
console.log(document.cookie); // "a=1; b=2; c=3; theme=dark"
// Only the first pair is a cookie; the rest are attributes for it.
document.cookie = 'x=1; y=2';
console.log(document.cookie.includes('y=2')); // false — y was read as an attribute
// Assigning empty string clears nothing.
document.cookie = '';
console.log(document.cookie); // still "a=1; b=2; c=3; theme=dark; x=1"go deeper
Remember that each assignment sets one cookie and leaves the others alone, and that the parts after the first semicolon are attributes for that cookie, not more cookies.
Explain the getter/setter asymmetry precisely, name the attributes script may set, and say why an omitted path scopes the cookie to the current directory rather than the site root.
Demonstrate that you treat cookie writes as unverifiable best-effort: read back when it matters, keep values small against the per-cookie and per-domain caps, and centralise writes in one helper that always sets path explicitly.
Own the convention across teams — who may write cookies from script at all, which values must instead be server-set so they can be HttpOnly, and how the per-request byte cost of the jar is budgeted.
## The setter is a command, not an assignment The single most surprising thing about `document.cookie` is that its getter and setter are asymmetric. Reading gives you the whole jar; writing operates on **one** cookie. The string you assign is parsed the way the browser parses a `Set-Cookie` response header value: a `name=value` pair, then optional `;`-separated attributes. ```js document.cookie; // "a=1; b=2; c=3" document.cookie = 'theme=dark; path=/; max-age=3600'; document.cookie; // "a=1; b=2; c=3; theme=dark" ``` Because of this, several intuitions that come from ordinary properties are wrong: - `document.cookie = ''` does **not** empty the jar. It is a malformed directive and does nothing useful. - You cannot write two cookies in one assignment. `"a=1; b=2"` sets `a` to `1` and treats `b=2` as an unrecognised attribute, which is ignored. - Assigning the same name again replaces that cookie's value *if the path and domain also match*; with a different path you get a second, separate cookie of the same name. ## Which attributes you may set from script The writable set is `Path`, `Domain`, `Expires`, `Max-Age`, `Secure`, `SameSite` and `Partitioned`. Attribute names are case-insensitive. Two are worth calling out because they change the cookie's lifetime: - **No `Expires` and no `Max-Age`** produces a *session cookie*: it lives in memory for the browsing session and disappears when the browser decides the session is over. - `Max-Age=3600` is a relative lifetime in seconds; `Expires` takes an absolute HTTP date string. When both are present, `Max-Age` wins. One attribute is deliberately **not** settable from script: `HttpOnly`. A cookie written by `document.cookie` can never be HttpOnly, which is the whole point — only the server can create a cookie script must not read. ## Defaults you inherit if you omit `path` Omitting `path` does not mean "site-wide". The default path is derived from the current document's URL — effectively the directory portion of it. Writing a cookie from `/app/settings` without a path scopes it to `/app`, and code running at `/` will not see it. This is the number-one cause of "my cookie vanished when the user navigated", so write `path=/` deliberately whenever you want site-wide scope. The `Domain` default is similar: omitting it produces a *host-only* cookie for exactly the current host, while setting `domain=example.com` widens it to subdomains. You can only widen to a domain the current document is within; a write naming an unrelated domain is rejected. ## The write is silent, and that matters There is no return value, no promise, and no exception. If the browser rejects the write — value over the ~4 KB budget, per-domain cookie cap exceeded, `Secure` requested from an insecure page, a `Domain` you are not entitled to — nothing happens and your code proceeds as if it succeeded. The only way to check is to read `document.cookie` back and look for the pair, and even that cannot confirm the attributes took effect: ```js document.cookie = 'theme=dark; path=/; max-age=3600'; if (!document.cookie.split('; ').some((p) => p.startsWith('theme='))) { // write was rejected — quota, or a Secure/Domain problem } ``` ## Encoding is your job A raw `;` inside a value terminates the pair and turns the remainder into garbage attributes; `,` and whitespace are likewise unsafe. Always `encodeURIComponent` the value (and the name, if it is dynamic) on write and decode on read. The API performs no escaping of its own. ## The round-trip asymmetry, stated plainly Everything you write except `name=value` is invisible afterwards. There is no `document.cookie` query for "what path is this on" or "when does it expire". That asymmetry drives real design decisions: if your code needs to know a cookie's expiry, it must encode that into the value or keep it in another store — and it is the main reason the promise-based cookie API, which returns objects carrying the attributes, exists at all.
- Your code writes a cookie from a page at `/app/settings` without a `path` attribute. Where is it readable?Only under `/app`, because the default path is derived from the current document's URL rather than defaulting to the site root. Navigate to `/` or `/checkout` and the cookie is filtered out of `document.cookie` and not sent on those requests. Always write `path=/` explicitly when you mean site-wide; the default is a scope decision you should not leave implicit.
- Can script create an HttpOnly cookie by including `httponly` in the string?No. `HttpOnly` is not in the set of attributes the `document.cookie` setter honours, and browsers ignore it there. A cookie that script must not read can only be created by the server via `Set-Cookie`. That asymmetry is deliberate: if script could mint HttpOnly cookies, the flag would give no guarantee about which cookies script has ever handled.
- How do you know whether a cookie write actually succeeded?Only by reading `document.cookie` back and checking that the pair appears; the setter returns nothing and throws nothing. Even then you have confirmed the name and value only — you cannot verify that `Secure`, `SameSite` or the expiry were applied, because the getter never returns attributes. Treat cookie writes as best-effort and keep values small.
saying these in an interview costs you the question
- Thinks assigning to document.cookie replaces the entire cookie string
- Believes one assignment can set several cookies at once
- Expects an exception or false return when the write is rejected
- Assumes an omitted path means the whole site
- Thinks script can set HttpOnly on a cookie it writes