JavaScript Language Overview
- Description: What JavaScript is, where it runs, the ECMAScript versions, strict mode, source structure (scripts vs modules), and the relationship to HTML/CSS in the browser.
- My Notion Note ID: K2A-F4-1
- Created: 2018-03-23
- Updated: 2026-05-17
- License: Reuse is very welcome. Please credit Yu Zhang and link back to the original on yuzhang.io
Table of Contents
- 1. What JavaScript Is
- 2. Where JavaScript Runs
- 3. ECMAScript Versions
- 4. Embedding in HTML
- 5. Scripts vs Modules
- 6. Strict Mode
- 7. Syntax Essentials
- 8. Comments and Style
- 9. References
1. What JavaScript Is
JavaScript is a dynamically typed, lexically scoped, single-threaded, multi-paradigm language standardised as ECMAScript by TC39. Multi-paradigm means imperative, object-oriented (prototype-based), and functional features all coexist.
In a browser, JavaScript is the behaviour layer:
| Layer | Language |
|---|---|
| Content / structure | HTML |
| Presentation | CSS |
| Behaviour / interactivity | JavaScript |
The name dates to 1995 (Netscape, originally LiveScript). It is unrelated to Java despite the name. The standardised dialect is ECMAScript (ES); "JavaScript" colloquially means ES + the browser/Node API surfaces.
2. Where JavaScript Runs
| Host | Engine | Runtime APIs |
|---|---|---|
| Chrome / Edge / Opera | V8 | DOM, BOM, Web APIs |
| Firefox | SpiderMonkey | DOM, BOM, Web APIs |
| Safari | JavaScriptCore | DOM, BOM, Web APIs |
| Node.js | V8 | Filesystem, network, child processes, modules |
| Deno | V8 + Rust runtime | Web-platform-compatible APIs + permissions |
| Bun | JavaScriptCore + Zig | Node-compatible APIs, faster startup |
| Cloudflare Workers / Vercel Edge | V8 isolates | Subset of Web APIs (Fetch, Streams, KV) |
| Embedded (e.g. QuickJS) | Various | Whatever the host provides |
The engine parses and executes JS; the runtime provides the host-specific APIs. Same engine, different runtimes — V8 in Chrome exposes document, V8 in Node exposes fs.
3. ECMAScript Versions
| Year | Edition | Notable additions |
|---|---|---|
| 1997 | ES1 | Initial standard. |
| 1999 | ES3 | try/catch, regex literals. Long the browser baseline. |
| 2009 | ES5 | strict mode, JSON, Object.create, getters/setters, array iteration (forEach, map). |
| 2015 | ES6 / ES2015 | let, const, arrow functions, classes, modules, template literals, Promise, Map/Set, destructuring, spread/rest, default params, for…of. The biggest jump in years. |
| 2016 | ES2016 | **, Array.prototype.includes. |
| 2017 | ES2017 | async/await, Object.entries/values. |
| 2018 | ES2018 | Rest/spread for objects, async iterators, regex improvements. |
| 2019 | ES2019 | Array.flat, Object.fromEntries, optional catch binding. |
| 2020 | ES2020 | Optional chaining ?., nullish coalescing ??, BigInt, dynamic import(), globalThis. |
| 2021 | ES2021 | ??=, ` |
| 2022 | ES2022 | Class fields, private methods, top-level await, Object.hasOwn, Array.at. |
| 2023 | ES2023 | Array.findLast, toSorted/toReversed (non-mutating). |
| 2024 | ES2024 | Promise.withResolvers, RegExp v flag, Object.groupBy. |
| 2025 | ES2025 | Iterator helpers (map/filter/take on iterators), Promise.try, sync Set methods. |
Since 2015 the spec ships annually with whatever proposals reached Stage 4. Compatibility tables: https://compat-table.github.io/compat-table/es2016plus/.
4. Embedding in HTML
<!-- External — preferred. Cached, smaller HTML, easier to maintain. -->
<script src="/app.js"></script>
<!-- Inline -->
<script>
console.log('Hello');
</script>
<!-- ES module — opt-in, deferred by default -->
<script type="module" src="/main.js"></script>
<!-- Skip execution in browsers that lack module support -->
<script nomodule src="/legacy.js"></script>
Attributes that change when the script runs:
| Attribute | Behaviour |
|---|---|
| (none) | Block parsing, fetch, execute. Slowest. |
defer |
Fetch in parallel, execute after HTML parsing in document order. Use for scripts that need the DOM ready. |
async |
Fetch in parallel, execute as soon as fetched. Order not guaranteed. Use for independent analytics/ads. |
type="module" |
Implicitly deferred. Plus module semantics. |
Rule of thumb: external <script defer src=…> in <head> for almost everything. Modules in <head> are fine too — they defer by default.
5. Scripts vs Modules
Two different parse modes; differences matter daily.
| Feature | Classic script | ES module (type="module" or .mjs) |
|---|---|---|
import/export |
No | Yes |
Top-level await |
No | Yes |
this at top level |
globalThis (browser: window) |
undefined |
| Strict mode | Opt-in via "use strict" |
Always on |
| Variables in top-level scope | Polluting global | Module-scoped only |
| Loading | Synchronous unless defer/async |
Deferred + executed once even if imported twice |
| CORS | Cross-origin allowed without CORS headers (legacy "no-cors" load — response is opaque to JS) | Cross-origin requires CORS headers (Access-Control-Allow-Origin) |
In Node:
.jsfiles inherit module type frompackage.json"type"field ("module"or"commonjs")..mjsforces ESM,.cjsforces CommonJS, regardless ofpackage.json.
6. Strict Mode
'use strict'; // first statement in a file or function
Strict mode tightens the language:
- Assignment to an undeclared variable throws instead of creating a global.
- Duplicate parameter names throw at parse time. (Duplicate object literal keys were a strict-mode error in ES5 but became legal again in ES2015 — needed for computed keys.)
thisisundefinedin plain functions called without an object (not coerced toglobalThis).deleteon a non-configurable property throws.withstatement banned.evalruns in its own scope; can't inject vars into the surrounding scope.
ES modules are always strict. Class bodies are always strict. New code rarely benefits from non-strict mode.
7. Syntax Essentials
7.1 Statements and Semicolons
const x = 1
const y = 2
console.log(x + y)
Semicolons are optional thanks to Automatic Semicolon Insertion (ASI). Two pitfalls where ASI doesn't insert and you need explicit semicolons:
const a = b + c
;[1, 2, 3].forEach(...) // leading [ would otherwise be treated as index access
const f = () => {}
;(() => { /* IIFE */ })() // leading ( would call f
Codebase convention is what matters. Either always include semicolons (Airbnb style) or always omit and prefix the few risky lines with ; (Prettier's "no-semi" style). Don't mix.
7.2 Variable Declarations
let count = 0; // block-scoped, reassignable
const PI = 3.14; // block-scoped, not reassignable
var x = 1; // function-scoped, hoisted, legacy
| Keyword | Scope | Reassignable | Hoisted |
|---|---|---|---|
const |
Block | No | Yes (TDZ until declaration) |
let |
Block | Yes | Yes (TDZ until declaration) |
var |
Function or global | Yes | Yes, initialised to undefined |
TDZ (Temporal Dead Zone) — for let/const, the variable exists from the start of the block but throws ReferenceError until the declaration line executes:
console.log(x); // ReferenceError
let x = 5;
var is the historical declaration. New code should use let/const exclusively.
Prefer const. Use let only when you need to reassign. Reassignment is rarer than people think — const obj = {}; obj.x = 1; is fine because we're mutating, not reassigning.
7.3 Identifiers
- Start with letter,
_, or$; can include digits after. - Case-sensitive (
name≠Name). - Unicode allowed (
const π = 3.14;). - Reserved words can't be used as identifiers (
for,class,return, etc.).
8. Comments and Style
// Single-line comment
/*
* Multi-line comment.
*/
/**
* JSDoc comment — semantic for tooling.
* @param {string} name
* @returns {string}
*/
function greet(name) {
return `Hello, ${name}`;
}
JSDoc annotations power IDE tooltips and TypeScript type checking on .js files (// @ts-check).
Conventions (informal but widely used):
camelCasefor variables and functions.PascalCasefor classes and constructors.SCREAMING_SNAKE_CASEfor compile-time-ish constants._leadingUnderscorefor "intended-private" (no language-level effect; classes have#for real private fields).- Two-space indentation (most communities). Four spaces in some legacy codebases.
Tooling:
- ESLint — finds bugs and enforces style. Configurable rules.
- Prettier — opinionated formatter. Drop-in, almost no config.
- TypeScript — adds static types. Worth adopting for anything beyond a script.
9. References
- ECMAScript spec — https://tc39.es/ecma262/
- TC39 proposals — https://github.com/tc39/proposals
- MDN JavaScript guide — https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide
- compat-table (browser/runtime support) — https://compat-table.github.io/compat-table/es2016plus/
- See also: javascript-types-and-operators