πŸŽ“ Velnov

🟨 JavaScript · Topic 20 of 20

Fetch, JSON & Modules β€” JavaScript Questions with Answers

30 practice questions on Fetch, JSON & Modules, each with the correct answer and a clear explanation of why it is right. Read through them as revision notes, or take this topic as an interactive quiz to test yourself.

1 easy Β· 17 medium Β· 12 hard Β· Part of JavaScript: The language of the web - basics to advanced, 20 topics.

Key concepts in this topic

fetchPromisesresponse.okError handlingstatusPOSTJSONHeadersJSON.stringifySerializationAPIsJSON.parseJSON limitationslocalStorageWeb StorageCORSSecurityAuthenticationAbortControllerResponse methodsStreamscloneModulesexport

Jump to: Easy Β· Medium Β· Hard

Easy questions (1)

Q1. easy

What does fetch(url) return?

const res = await fetch(url);
const data = await res.json();
  1. A A promise that resolves to a Response object
  2. B The data directly
  3. C A string
  4. D undefined

Answer: A β€” A promise that resolves to a Response object

fetch is asynchronous: it resolves once the response HEADERS arrive. You then read the body with .json(), .text() or .blob() - each of which is also async.

fetchPromises

Medium questions (17)

Q3. medium

What does response.ok tell you?

  1. A true when the status is in the 200-299 range
  2. B That the network worked
  3. C That JSON parsed correctly
  4. D Nothing useful

Answer: A β€” true when the status is in the 200-299 range

A quick success test. response.status gives the exact code (404, 500...) for more specific handling.

response.okstatus

Q4. medium

How do you send a POST request with JSON?

  1. A fetch(url, { method: "POST", headers: {"Content-Type": "application/json"}, body: JSON.stringify(data) })
  2. B fetch(url, data)
  3. C fetch.post(url, data)
  4. D fetch(url, { post: data })

Answer: A β€” fetch(url, { method: "POST", headers: {"Content-Type": "application/json"}, body: JSON.stringify(data) })

Three parts matter: the method, the Content-Type header so the server parses it correctly, and a STRINGIFIED body (fetch cannot send a raw object).

POSTJSONHeaders

Q6. medium

What is JSON?

  1. A A text format for structured data, based on JavaScript object syntax but language-independent
  2. B A JavaScript library
  3. C A database
  4. D A type of function

Answer: A β€” A text format for structured data, based on JavaScript object syntax but language-independent

JavaScript Object Notation is the standard way APIs exchange data. It supports objects, arrays, strings, numbers, booleans and null - but not functions, undefined or comments.

JSONAPIs

Q7. medium

What is the difference between JSON.parse and JSON.stringify?

  1. A parse turns a JSON STRING into a JS value; stringify turns a JS value into a JSON string
  2. B They are the same
  3. C parse converts to a string
  4. D stringify validates JSON

Answer: A β€” parse turns a JSON STRING into a JS value; stringify turns a JS value into a JSON string

Mnemonic: parse comes IN (from text), stringify goes OUT (to text). Wrap JSON.parse of untrusted input in try/catch - malformed JSON throws a SyntaxError.

JSON.parseJSON.stringify

Q9. medium

How do you store an object in localStorage?

localStorage.setItem("user", JSON.stringify(user));
const user = JSON.parse(localStorage.getItem("user") ?? "null");
  1. A localStorage.setItem("key", JSON.stringify(obj)) then JSON.parse on read
  2. B localStorage.setItem("key", obj)
  3. C localStorage.obj = obj
  4. D Objects cannot be stored

Answer: A β€” localStorage.setItem("key", JSON.stringify(obj)) then JSON.parse on read

localStorage stores STRINGS only; saving an object directly gives "[object Object]". Always stringify on write and parse on read.

localStorageJSON

Q10. medium

What is the difference between localStorage and sessionStorage?

  1. A localStorage persists until cleared; sessionStorage is wiped when the tab closes
  2. B They are identical
  3. C sessionStorage is bigger
  4. D localStorage is per-tab

Answer: A β€” localStorage persists until cleared; sessionStorage is wiped when the tab closes

Both store strings per origin (roughly 5-10 MB). Choose sessionStorage for temporary per-tab state, localStorage for preferences that should survive restarts.

Web Storage

Q12. medium

How do you send an authorisation token with fetch?

fetch(url, { headers: { Authorization: `Bearer ${token}` } });
  1. A In the headers object: { Authorization: `Bearer ${token}` }
  2. B In the URL always
  3. C In the method
  4. D Tokens cannot be sent

Answer: A β€” In the headers object: { Authorization: `Bearer ${token}` }

Headers carry auth data. Avoid putting tokens in URLs, where they leak into logs and browser history.

HeadersAuthentication

Q14. medium

How do you read a plain-text response?

  1. A await response.text()
  2. B response.body
  3. C response.string()
  4. D response.data

Answer: A β€” await response.text()

Body readers: .json() for JSON, .text() for text/HTML, .blob() for binary (images, files), .formData() for form payloads.

Response methods

Q16. medium

What does export do in an ES module?

export const PI = 3.14;
export function area(r) { }
export default class Circle { }
  1. A Makes a value available for other modules to import
  2. B Sends data to the server
  3. C Saves a file
  4. D Deletes a variable

Answer: A β€” Makes a value available for other modules to import

Modules are private by default; export opens specific values to others. A file can have many NAMED exports and at most one DEFAULT export.

Modulesexport

Q17. medium

What is the difference between a named and a default export?

import { area, PI } from "./math.js";
import Circle from "./circle.js";        // any name works
import { area as calcArea } from "./math.js";   // rename
  1. A Named exports must be imported by their exact name in braces; a default export can be imported under any name
  2. B They are identical
  3. C Default exports are faster
  4. D You can have many defaults

Answer: A β€” Named exports must be imported by their exact name in braces; a default export can be imported under any name

Named imports use braces and exact names (better for autocomplete and refactoring); default imports pick their own name.

importexport

Q18. medium

How do you enable ES modules in a browser?

  1. A <script type="module" src="app.js"></script>
  2. B <script module>
  3. C Modules work automatically
  4. D <module src="app.js">

Answer: A β€” <script type="module" src="app.js"></script>

type="module" also implies defer and strict mode, and gives the file its own scope. Modules must be served over http(s), not opened via file://.

type=moduleScripts

Q20. medium

What scope do variables in a module have?

  1. A Module scope - private to that file unless exported
  2. B Global scope
  3. C Function scope only
  4. D No scope

Answer: A β€” Module scope - private to that file unless exported

This is a major advantage over classic scripts, where top-level var became global and could clash between files.

Module scope

Q22. medium

Are ES module imports hoisted?

  1. A Yes - imports are resolved before any module code runs, so import order in the file does not matter
  2. B No
  3. C Only default imports
  4. D Only in Node

Answer: A β€” Yes - imports are resolved before any module code runs, so import order in the file does not matter

The module graph is built first, then code executes. Convention is still to put imports at the top for readability.

HoistingModules

Q25. medium

How do you handle a fetch that might fail?

try {
  const res = await fetch(url);
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return await res.json();
} catch (err) {
  showError(err.message);
}
  1. A try/catch around await, plus a response.ok check inside
  2. B Only try/catch
  3. C Only response.ok
  4. D Fetch never fails

Answer: A β€” try/catch around await, plus a response.ok check inside

You need BOTH: catch handles network/CORS failures, while the ok check handles HTTP error statuses that resolve normally.

Error handlingfetch

Q26. medium

What does the async attribute do on a script tag?

  1. A Downloads in parallel and executes as soon as ready - order is NOT guaranteed
  2. B Same as defer
  3. C Delays the script
  4. D Makes functions async

Answer: A β€” Downloads in parallel and executes as soon as ready - order is NOT guaranteed

Use async for independent scripts like analytics. Use defer when scripts depend on the DOM or on each other, since defer preserves order and waits for parsing.

asyncdefer

Q28. medium

How do you send FORM data (including files) with fetch?

const fd = new FormData(form);
fetch(url, { method: "POST", body: fd });
  1. A Pass a FormData object as the body - and do NOT set Content-Type manually
  2. B JSON.stringify the form
  3. C Send it in the URL
  4. D Files cannot be sent

Answer: A β€” Pass a FormData object as the body - and do NOT set Content-Type manually

The browser sets the correct multipart Content-Type with its boundary automatically; setting it yourself breaks the upload.

FormDataFile upload

Q30. medium

What is the modern replacement for XMLHttpRequest?

  1. A fetch - promise-based and much cleaner
  2. B jQuery.ajax
  3. C WebSocket
  4. D There is none

Answer: A β€” fetch - promise-based and much cleaner

fetch is built in, returns promises and works naturally with async/await. XHR still appears in legacy code and for upload-progress events, which fetch handles less directly.

fetchXMLHttpRequest

Hard questions (12)

Q2. hard

Does fetch REJECT on a 404 or 500 response?

const res = await fetch(url);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
  1. A No - it only rejects on network failure; HTTP errors still resolve successfully
  2. B Yes, it rejects on any error status
  3. C Only on 500
  4. D It throws a SyntaxError

Answer: A β€” No - it only rejects on network failure; HTTP errors still resolve successfully

This surprises almost everyone. You must check response.ok (true for 200-299) and throw yourself, otherwise .catch() never sees server errors.

  • The most common fetch bug in real projects.

response.okError handling

Q5. hard

Why must the body be JSON.stringify(data) rather than the object itself?

  1. A HTTP bodies are text/bytes - passing an object would send "[object Object]"
  2. B It is optional
  3. C To encrypt it
  4. D To compress it

Answer: A β€” HTTP bodies are text/bytes - passing an object would send "[object Object]"

The object must be serialised to a JSON string. On the server it is parsed back; in the browser, response.json() does the reverse.

JSON.stringifySerialization

Q8. hard

Which values are LOST by JSON.stringify?

JSON.stringify({ a: 1, f() {}, u: undefined });   // '{"a":1}'
  1. A Functions, undefined values and symbols are dropped; Dates become strings
  2. B Nothing is lost
  3. C Numbers are lost
  4. D Only arrays survive

Answer: A β€” Functions, undefined values and symbols are dropped; Dates become strings

JSON has no concept of functions or undefined, so those keys vanish. Dates serialise to ISO strings and do NOT come back as Date objects - a frequent source of bugs.

JSON limitations

Q11. hard

What is CORS?

  1. A A browser security rule requiring the server to permit cross-origin requests via response headers
  2. B A JavaScript library
  3. C A type of promise
  4. D An encoding format

Answer: A β€” A browser security rule requiring the server to permit cross-origin requests via response headers

By default a page cannot read responses from another origin. The SERVER must send Access-Control-Allow-Origin. CORS errors cannot be fixed from client-side JavaScript alone.

CORSSecurity

Q13. hard

How do you CANCEL an in-flight fetch request?

const ac = new AbortController();
fetch(url, { signal: ac.signal });
ac.abort();
  1. A With an AbortController and its signal
  2. B fetch.cancel()
  3. C clearTimeout(fetch)
  4. D You cannot cancel it

Answer: A β€” With an AbortController and its signal

Essential for search-as-you-type (cancel the previous request) and for cleanup when a component unmounts. The aborted promise rejects with an AbortError.

AbortController

Q15. hard

Why can a response body be read only ONCE?

  1. A It is a stream - after reading it is consumed; clone the response if you need it twice
  2. B A browser bug
  3. C For security
  4. D It can be read many times

Answer: A β€” It is a stream - after reading it is consumed; clone the response if you need it twice

Calling both .json() and .text() on the same response throws 'body stream already read'. Use response.clone() when you truly need two reads.

Streamsclone

Q19. hard

Why do ES modules require a server (not file://)?

  1. A Module loading is subject to CORS, which does not apply to the file protocol
  2. B Modules need a database
  3. C Browsers ban local files entirely
  4. D They do work with file://

Answer: A β€” Module loading is subject to CORS, which does not apply to the file protocol

Opening an HTML file directly gives a CORS error for module imports. Use a local server (VS Code Live Server, python -m http.server) during development.

CORSModules

Q21. hard

What is dynamic import()?

button.onclick = async () => {
  const { Chart } = await import("./chart.js");
  new Chart();
};
  1. A import("./mod.js") returns a PROMISE, letting you load a module on demand at runtime
  2. B A faster static import
  3. C Importing many files at once
  4. D A deprecated feature

Answer: A β€” import("./mod.js") returns a PROMISE, letting you load a module on demand at runtime

Static imports are hoisted and always loaded. Dynamic import enables code splitting and lazy loading - only fetching a heavy module when the user actually needs it.

Dynamic importCode splitting

Q23. hard

What is the difference between ES modules and CommonJS?

  1. A ESM uses import/export and is static/async; CommonJS uses require()/module.exports and is synchronous (Node's older system)
  2. B They are the same
  3. C CommonJS is browser-only
  4. D ESM is deprecated

Answer: A β€” ESM uses import/export and is static/async; CommonJS uses require()/module.exports and is synchronous (Node's older system)

Browsers support ESM natively; Node supports both (.mjs or "type": "module" for ESM). ESM's static structure enables tree-shaking during bundling.

CommonJSNode.js

Q24. hard

What is tree-shaking?

  1. A Bundlers removing exported code that is never imported, shrinking the final file
  2. B Sorting the DOM tree
  3. C Clearing the cache
  4. D A debugging technique

Answer: A β€” Bundlers removing exported code that is never imported, shrinking the final file

It works because ES module imports are static and analysable. Importing one function from a library can leave the rest out of your bundle.

BundlersOptimisation

Q27. hard

What does the URLSearchParams API help with?

const p = new URLSearchParams({ q: "js books", page: 2 });
fetch(`/search?${p}`);   // /search?q=js+books&page=2
  1. A Building and reading query strings safely, with proper encoding
  2. B Parsing JSON
  3. C Creating modules
  4. D Storing cookies

Answer: A β€” Building and reading query strings safely, with proper encoding

Manual string concatenation breaks with spaces and special characters. URLSearchParams encodes values correctly.

URLSearchParamsQuery strings

Q29. hard

Why should API keys never be stored in front-end JavaScript?

  1. A All client code is visible to users - anyone can read the key from DevTools or the bundle
  2. B It makes the site slow
  3. C Browsers block them
  4. D It is fine to store them

Answer: A β€” All client code is visible to users - anyone can read the key from DevTools or the bundle

Minification is not security. Secret keys belong on a server that proxies the request; the browser calls YOUR endpoint instead.

SecurityAPI keys

Practice β€œFetch, JSON & Modules” as a quiz