100+ JavaScript Concepts you Need to Know
Based on Fireship's video on YouTube. If you like this content, support the original creators by watching, liking and subscribing to their content.
JavaScript’s reach spans browsers and servers, with ECMAScript as the browser standard and Node.js enabling server-side execution.
Briefing
JavaScript’s core appeal is that it runs almost everywhere—directly in browsers and also on servers—while its core challenge is that the language’s “weirdness” comes from how it works under the hood: prototypal objects, dynamic typing, and an event-driven runtime. That combination is why mastering JavaScript can unlock web, mobile, desktop, server, and even AI work, but also why developers often get tripped up by confusing edge cases and a crowded ecosystem of frameworks and libraries.
Created in 1993 at Netscape by Brendan Eich, JavaScript was originally built to make early web pages interactive, replacing static HTML with code that could respond to user actions. Today, its standard implementation is ECMAScript, the default language in web browsers. In the browser, JavaScript is the only natively running code besides WebAssembly, but it’s not limited to the client: Node.js and Dino enable JavaScript to run on servers too. In practice, JavaScript is executed line-by-line (interpreted), yet modern browsers accelerate it using the V8 engine with Just in Time compilation that converts code to machine code.
On the language fundamentals, JavaScript uses console.log for output and supports multiple variable declarations: let for modern code, const for values that shouldn’t be reassigned, and var as an older option best avoided. Variables are dynamically typed, so they don’t require type annotations; a variable can start as undefined, be set to null for an explicit empty value, and later be reassigned to a different primitive type. Scoping is central: global scope makes variables accessible everywhere, function scope limits them to the function, and block scope applies inside braces—except var, which behaves differently by being hoisted into the function scope.
Functions are treated as first-class objects. They can be declared normally, used as expressions, nested to create closures, and passed around for higher-order patterns. The value of this depends on how a function is called: in the global context it points to window, but when attached to an object it points to that object; bind can manually set the target. Argument passing differs too: primitives are passed by value (copies), while objects are passed by reference (shared heap data), which makes mutation a real concern.
Objects rely on a prototype chain rather than classical inheritance. Even though JavaScript offers a class keyword, classes are described as syntactic sugar over prototypal inheritance, with constructors, instance methods, and optional static methods. Built-in data structures include arrays, sets, and maps; memory management is handled by garbage collection, with WeakMap and WeakSet designed so entries can be collected when no longer referenced.
The runtime model is non-blocking thanks to the event loop. Synchronous code runs on the main thread, while asynchronous work is queued and resumed later. setTimeout demonstrates callback scheduling, but deep nesting leads to callback hell. Promises provide a cleaner path: they represent a value that will resolve later (or reject on error), and async/await makes the control flow readable. Error handling typically uses try/catch.
As apps scale, modules help split code across files using export and import. For third-party dependencies, npm installs packages into node_modules and tracks them in package.json. On the browser side, the Document Object Model represents the UI as a tree of nodes; querySelector and querySelectorAll locate elements, and addEventListener wires UI updates to events. Many teams avoid “imperative” DOM mutation by using frameworks that render declaratively from reactive data and component trees.
Finally, production code usually needs bundling via tools like V or webpack, with dynamic imports to split large bundles and improve load performance. JavaScript’s reach extends to desktop and mobile via Electron and React Native. For maintainability, TypeScript or ES lint can add static analysis and guardrails—an antidote to the language’s flexibility and the ecosystem’s complexity.
Cornell Notes
JavaScript is a widely deployable language: it runs natively in browsers (via ECMAScript) and also on servers through runtimes like Node.js. Under the hood, performance comes from engines such as V8 using Just in Time compilation, while the runtime model relies on a non-blocking event loop. Core language mechanics include dynamic typing, multiple variable declarations (let/const/var), scoping rules, first-class functions (closures, this-binding), and prototypal inheritance via the prototype chain. Asynchronous work is handled with callbacks, then improved with Promises and async/await for readable control flow and try/catch error handling. For larger projects, modules, npm, DOM APIs, bundlers, and optional tooling like TypeScript or ES lint help manage complexity and performance.
Why does JavaScript feel “different” compared with languages that compile ahead of time?
How do let, const, and var differ in practical terms?
What makes closures powerful, and how does memory placement relate to them?
How does this work in JavaScript, and why can it be confusing?
What’s the difference between callbacks, Promises, and async/await for asynchronous code?
How do modern web apps avoid manual DOM mutation in vanilla JavaScript?
Review Questions
- Explain how scoping differs between global scope, function scope, and block scope, and why var is singled out as problematic.
- Describe how the event loop supports non-blocking behavior, and compare callback hell with the promise/async-await approach.
- What are prototype chains, and how do classes relate to prototypal inheritance in JavaScript?
Key Points
- 1
JavaScript’s reach spans browsers and servers, with ECMAScript as the browser standard and Node.js enabling server-side execution.
- 2
V8’s Just in Time compilation helps make dynamic, line-by-line JavaScript fast enough for real-world apps.
- 3
let, const, and var differ mainly in reassignment rules and scoping behavior; var’s hoisting and lack of block scope often cause bugs.
- 4
Functions are first-class: closures preserve outer variables via heap persistence, and this-binding depends on call-site context.
- 5
Asynchronous control flow moves from callbacks (event-loop queued) to Promises and async/await for clearer logic and consistent error handling with try/catch.
- 6
JavaScript objects inherit through the prototype chain; the class keyword is syntactic sugar over prototypal inheritance.
- 7
Scaling JavaScript typically requires modules, npm for dependencies, and bundlers (with dynamic imports) to manage performance and load size.