JavaScript
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax and Types
-
Section 3: Strings and Numbers in Depth
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Objects and Arrays
-
Section 7: Maps, Sets, and Symbols
-
Section 8: Asynchronous JavaScript
-
Section 9: Object-Oriented and Prototypes
-
Section 10: The DOM
-
Section 11: Browser APIs
-
Section 12: Modern JavaScript (ES2015-ES2025)
-
Section 13: Functional Programming Patterns
-
Section 14: Error Handling and Debugging
-
Section 15: Testing
-
Section 16: Accessibility for JavaScript Developers
-
Section 17: Internationalization and Localization
-
Section 18: Performance
-
Section 19: Node.js Fundamentals
-
Section 20: Regular Expressions
-
Section 21: Design Patterns in JavaScript
-
Section 22: Security Basics
-
Section 23: Data Structures and Algorithms in JavaScript
-
Section 24: Practical Projects
-
Section 25: More Advanced Async Patterns
-
Section 26: More Object and Class Practice
-
Section 27: Working with Dates and Internationalization
-
Section 28: Web Components
-
Section 29: More DOM and Browser Practice
-
Section 30: Build Tooling for Vanilla JavaScript
-
Section 31: More Practice Projects
-
Section 32: Interview and Algorithm Practice
-
Section 33: Error Objects (MDN Reference)
-
Section 34: TypedArrays and Binary Data
-
Section 35: Reflection and Metaprogramming (MDN Reference)
-
Section 36: More Global Functions (MDN Reference)
1: JavaScript in the Browser and Node.js
A few years ago, I was onboarding a junior developer who had spent the morning writing a clever script to scrape some data from a webpage using document.querySelectorAll. He wanted to test a specific piece of the logic in isolation, so he opened his terminal and ran node script.js. He immediately hit a ReferenceError: document is not defined and spent twenty minutes convinced that his Node.js installation was corrupted. He hadn't broken anything; he had just run into the fundamental wall between the two primary environments where JavaScript lives.
The Global Context Shift
Here is the thing that trips people up: JavaScript, the language itself (ECMAScript), is just a set of rules for how to handle variables, loops, and functions. But the language doesn't actually do anything on its own. It needs a runtime—an engine that executes the code. When you run JS in a browser, the runtime provides a global object called window. When you run it in Node.js, that global object is called global.
I like to think of it as the same driver (JavaScript) operating two completely different vehicles. In the browser, the vehicle is a car designed for navigation and visuals. In Node, the vehicle is a heavy-duty truck designed for hauling files and managing network traffic. If you try to turn on the windshield wipers (the DOM) while you're driving the truck, you're going to be confused when you find there aren't any.
Where the DOM Lives (And Where It Doesn't)
In the browser, JavaScript's primary job is to talk to the Document Object Model (DOM). This is why you have access to window, document, and localStorage. These aren't actually part of the JavaScript language; they are Web APIs provided by the browser. If you're writing code that manipulates a <div> or listens for a click event, that code is biologically incapable of running in Node.js because Node has no concept of a visual window or an HTML document.
// This works in Chrome, but crashes in Node
const header = document.querySelector('h1');
header.style.color = 'red';
Node's Server-Side Power
On the flip side, Node.js gives you superpowers that would be a massive security risk in a browser. For instance, Node allows you to read and write files directly to the hard drive using the fs module or check environment variables using process.env. If a random website you visited could suddenly use a filesystem API to read your .ssh folder, the internet would be a terrifying place. That's why Node has its own set of built-in modules that the browser will never see.
// This works in Node, but crashes in the browser
const fs = require('fs');
const data = fs.readFileSync('/etc/passwd', 'utf8');
console.log(data);
The sweet spot is writing "environment-agnostic" logic. If you write a function that calculates a price discount or formats a date, that's pure JavaScript. You can move that function between a React frontend and a Node backend without changing a single line of code. That's where the real power of the language lies.
📋 Practical Task
The Environment-Aware Logger
Your task is to create a single JavaScript file that can be executed in both a web browser and a Node.js environment. The script should detect which environment it is currently running in and perform a specific action for each:
- If running in the browser: Log the current window width (
window.innerWidth) to the console. - If running in Node.js: Log the current working directory (
process.cwd()) to the console.
Hint: You'll need to check for the existence of a global object that only exists in one of the two environments (like window or process) before attempting to access its properties.
There are no comments for now.