JavaScript is the one language your browser already runs. You don’t need an installer, an editor, or a build step. Press one key, type one line, and the engine executes it. This guide takes you from that first console command to a working Hello World page with an external script file, and explains what the engine does at each step.
Quick Takeaways
- Open the browser console with
F12orCtrl+Shift+J(Cmd+Option+Jon macOS) and type code directly. console.log()prints values to the console.alert()shows a pop-up.document.write()andtextContentchange the page.- For real projects, put JavaScript in an external
.jsfile and load it with a<script>tag. - Use
constby default,letwhen a value must change, and avoidvar.
| Method | Where Output Appears | Best For | Production Use |
|---|---|---|---|
console.log() |
DevTools console | Debugging, learning | Remove or gate behind a flag |
alert() |
Blocking pop-up | Quick demos only | Avoid |
document.write() |
Page body | Legacy examples | Avoid |
element.textContent |
A specific DOM node | Visible page output | Recommended |
Step 1: Open the Browser Console
Every modern browser ships with developer tools. The console is a REPL (read-eval-print loop): it reads a line, evaluates it, and prints the result.
| Browser | Windows / Linux | macOS |
|---|---|---|
| Chrome / Edge | F12 or Ctrl+Shift+J |
Cmd+Option+J |
| Firefox | F12 or Ctrl+Shift+K |
Cmd+Option+K |
| Safari | Enable Develop menu first | Cmd+Option+C |
In Safari, go to Settings → Advanced and tick “Show features for web developers” before the shortcut works.
Click the Console tab if DevTools opens on another panel. You will see a prompt (>) waiting for input.
Step 2: Run Your First Line
Type this into the console and press Enter:
console.log("Hello, World!");
The console prints:
Hello, World!
undefined
The first line is the output of console.log(). The second line, undefined, is the return value of the expression. console.log() returns nothing, so the REPL reports undefined. This is normal.
Syntax Breakdown
Each piece of that line has a job:
consoleis a built-in global object provided by the browser..logis a method on that object. The dot is the member-access operator.("Hello, World!")calls the method with one argument, a string.;ends the statement. JavaScript inserts semicolons automatically in many cases, but writing them avoids edge-case bugs.
Do Math Without Writing a Program
The console evaluates any expression. Try arithmetic:
2 + 2;
4
Expressions print their result automatically. You don’t need console.log() at the prompt. Inside a script file, you do.
Step 3: Store Values in Variables
A variable is a named reference to a value. Declare one with const or let.
// const: binding cannot be reassigned
const greeting = "Hello, World!";
// let: binding can be reassigned
let visitorCount = 0;
visitorCount = visitorCount + 1;
console.log(greeting);
console.log(visitorCount);
Hello, World!
1
greeting is locked to its string. Trying greeting = "Hi" throws a TypeError (“Assignment to constant variable”). visitorCount changes freely.
const vs. let vs. var
| Keyword | Scope | Reassignable | Hoisting Behavior | Recommendation |
|---|---|---|---|---|
const |
Block | No | Temporal dead zone | Default choice |
let |
Block | Yes | Temporal dead zone | Use when value changes |
var |
Function | Yes | Hoisted, initialized as undefined |
Avoid in new code |
const does not make objects immutable. It prevents rebinding the variable. You can still mutate an array or object stored in a const.
Step 4: Know the Core Data Types
JavaScript has seven primitive types and one structured type. Check any value with typeof.
console.log(typeof "text"); // "string"
console.log(typeof 42); // "number"
console.log(typeof true); // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof null); // "object" (a historic quirk)
console.log(typeof 10n); // "bigint"
console.log(typeof Symbol("id"));// "symbol"
console.log(typeof {}); // "object"
The typeof null result is a long-standing language bug, preserved for backward compatibility. Test for null with value === null.
Template Literals
Backticks create template literals. They interpolate expressions and support multi-line strings.
const name = "Ada";
const message = `Hello, ${name}! 2 + 3 = ${2 + 3}`;
console.log(message);
Hello, Ada! 2 + 3 = 5
The engine evaluates everything inside ${} and converts the result to a string. This replaces clumsy concatenation with +.
Step 5: Write a Function
A function packages reusable logic. Define one with the arrow syntax or the function keyword.
// Function declaration
function greet(name) {
return `Hello, ${name}!`;
}
// Arrow function (same behavior here)
const greetArrow = (name) => `Hello, ${name}!`;
console.log(greet("World"));
console.log(greetArrow("Console"));
Hello, World!
Hello, Console!
A declaration is hoisted, so you can call it before its definition. An arrow function stored in a const is not, and calling it early throws a ReferenceError.
Step 6: Move from the Console to a Real Page
Console code vanishes when you reload. To keep it, create a project folder with two files.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello World</title>
</head>
<body>
<h1 id="output">Loading...</h1>
<!-- defer: download now, execute after HTML is parsed -->
<script src="app.js" defer></script>
</body>
</html>
app.js
// Select the element by its id
const output = document.getElementById("output");
// Update the text safely (no HTML parsing)
output.textContent = "Hello, World!";
// Log for debugging
console.log("Script executed. Heading updated.");
Open index.html by double-clicking it. The heading changes from “Loading…” to “Hello, World!”, and the console shows your log message.
What Happens at Runtime
- The browser parses
index.htmltop to bottom and builds the DOM. - It starts downloading
app.jsin parallel because of thedeferattribute. - After parsing finishes, it runs
app.js. document.getElementById()returns the<h1>node.- Assigning to
textContentreplaces the node’s text and triggers a repaint.
Script Loading Strategies
| Attribute | Download | Execution | Preserves Order | Use Case |
|---|---|---|---|---|
| (none) | Blocks parsing | Immediately | Yes | Legacy pages |
defer |
Parallel | After DOM parsed | Yes | Most app scripts |
async |
Parallel | As soon as ready | No | Analytics, ads |
type="module" |
Parallel | After DOM parsed (deferred) | Yes | Modern ES modules |
Use defer as your default. Without it, a script in <head> runs before <body> exists, and getElementById() returns null.
Step 7: Respond to a User Click
Static text is a start. Interactivity comes from event listeners.
<!-- Add inside <body> in index.html -->
<button id="greet-btn">Say Hello</button>
// Add to app.js
const button = document.getElementById("greet-btn");
button.addEventListener("click", () => {
output.textContent = `Hello, World! Clicked at ${new Date().toLocaleTimeString()}`;
});
Each click runs the callback and rewrites the heading with the current time. The listener stays registered until the page unloads or you call removeEventListener().
Common Errors and How to Read Them
The console prints errors in red with a file name and line number. Click the link to jump to the source.
| Error Message | Cause | Fix |
|---|---|---|
ReferenceError: x is not defined |
Variable used before declaration or misspelled | Declare it, check spelling and case |
TypeError: Cannot set properties of null |
getElementById() found nothing |
Add defer, verify the id |
SyntaxError: Unexpected token |
Missing bracket, quote, or comma | Check the reported line and the one above |
TypeError: x is not a function |
Calling a non-function value | Log typeof x before the call |
Failed to load resource: 404 |
Wrong script path | Fix the src path relative to the HTML file |
JavaScript is case-sensitive. Console.log() fails. console.log() works.
Best Practices: Bad Code vs. Good Code
Anti-pattern 1: Global variables and var
// Bad: leaks to window, hoists unpredictably
var count = 0;
function increment() { count++; }
// Good: block-scoped, encapsulated in a module-style closure
const createCounter = () => {
let count = 0;
return { increment: () => ++count };
};
const counter = createCounter();
console.log(counter.increment()); // 1
Anti-pattern 2: Injecting raw HTML
// Bad: executes injected markup, opens an XSS hole
const userInput = "<img src=x onerror=alert('hacked')>";
document.getElementById("output").innerHTML = userInput;
// Good: treats input as plain text
document.getElementById("output").textContent = userInput;
innerHTML parses its input as HTML. textContent never does. Use textContent for any untrusted string.
Anti-pattern 3: Loose equality
// Bad: coercion produces surprises
console.log(0 == ""); // true
console.log("1" == 1); // true
// Good: strict equality compares type and value
console.log(0 === ""); // false
console.log("1" === 1); // false
The == operator coerces types using a complex rule set. === does not. Default to === and !==.
Anti-pattern 4: Debug logs left in production
// Bad
console.log("user token:", token);
// Good: gate logging behind an explicit flag
const DEBUG = false;
if (DEBUG) console.log("state:", state);
Never log secrets. Anyone can open the console on your live site.
Useful Console Methods Beyond log
| Method | Output | Example |
|---|---|---|
console.error() |
Red error line with stack trace | console.error("Failed") |
console.warn() |
Yellow warning | console.warn("Deprecated") |
console.table() |
Formatted table | console.table([{a:1},{a:2}]) |
console.time() / timeEnd() |
Elapsed milliseconds | Benchmark a block |
console.clear() |
Empties the console | Reset between tests |
console.time("loop");
let sum = 0;
for (let i = 0; i < 1_000_000; i++) sum += i;
console.timeEnd("loop");
console.log(sum);
loop: 2.4ms
499999500000
Timing varies by machine. The sum is deterministic. The loop runs in O(n) time, one pass over a million integers.
Where to Go Next
Build on this foundation in order:
- Conditionals and loops:
if,for,while, andfor...of. - Arrays and objects:
.map(),.filter(),.reduce(), destructuring. - DOM manipulation:
querySelector(),classList, creating elements. - Asynchronous code:
fetch(),Promise,async/await. - Tooling: Node.js, npm, and a bundler such as Vite.
Practice each concept in the console first. It gives instant feedback with zero setup.
FAQ
How do I run JavaScript in the browser console?
Press F12 (or Ctrl+Shift+J on Chrome, Cmd+Option+J on macOS), click the Console tab, type a statement such as console.log("Hello, World!");, and press Enter. The browser executes it immediately and prints the result.
What is the difference between the console and a script file?
The console runs code line by line and discards it on reload. A script file, loaded with <script src="app.js" defer></script>, persists on disk, runs automatically on each page load, and can be versioned, shared, and deployed.
Why does my script say “Cannot read properties of null”?
The script ran before the HTML element existed, or the id doesn’t match. Add the defer attribute to your <script> tag, or move the tag to the end of <body>. Then confirm the id in getElementById() matches the HTML exactly, including case.
Do I need to install anything to learn JavaScript?
No. Any modern browser includes a JavaScript engine and a console. A plain text editor and a browser are enough for your first projects. Install Node.js later when you want to run JavaScript outside the browser.




