How to Write Your First JavaScript Program: Hello, World!
Every programming journey begins with the same ritual: displaying "Hello, World!" on the screen. It may seem trivial, but this simple exercise teaches you something fundamental about JavaScript: how your code connects to an HTML page, where it runs, and the different ways it can produce output.
This guide takes you beyond a one-line copy-paste. You will learn exactly how the <script> tag works, why its placement in the HTML document matters, how to organize JavaScript in separate files, and the critical differences between the three main output methods. By the end, you will build a complete "Hello, World!" page that uses all three techniques.
Embedding JavaScript in HTML with the Script Tag
JavaScript does not run on its own in the browser. It needs an HTML document to live in. The <script> tag is the bridge between HTML and JavaScript. Everything between the opening <script> and closing </script> tags is treated as JavaScript code, not HTML.
Basic Inline Script
Here is the simplest possible way to run JavaScript inside an HTML page:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello World</title>
</head>
<body>
<h1>My First Page</h1>
<script>
console.log("Hello, World!");
</script>
</body>
</html>
When the browser reaches the <script> tag, it pauses HTML rendering, executes the JavaScript inside, and then continues rendering the rest of the page.
Script Tag Placement: Where It Goes Matters
You can place <script> tags in three locations: inside <head>, inside <body>, or at the end of <body>. Each placement behaves differently, and choosing the wrong one is one of the most common mistakes beginners make.
Placement 1: Inside <head> (problematic without attributes)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Script in Head</title>
<script>
// This will FAIL: the <p> element does not exist yet!
document.getElementById("greeting").textContent = "Hello!";
</script>
</head>
<body>
<p id="greeting">Original text</p>
</body>
</html>
Result: You get an error in the console:
Uncaught TypeError: Cannot set properties of null (setting 'textContent')
The JavaScript ran before the browser created the <p> element. At the moment the script executed, document.getElementById("greeting") returned null because that element did not exist yet.
Placement 2: At the end of <body> (recommended for beginners)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Script at End of Body</title>
</head>
<body>
<p id="greeting">Original text</p>
<!-- Script placed AFTER all HTML elements -->
<script>
// This works: the <p> element already exists
document.getElementById("greeting").textContent = "Hello, World!";
</script>
</body>
</html>
Result: The page displays "Hello, World!" correctly. By the time the script runs, all HTML elements above it have already been created.
Placement 3: Inside <head> with defer (modern best practice)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Script with Defer</title>
<script src="script.js" defer></script>
</head>
<body>
<p id="greeting">Original text</p>
</body>
</html>
The defer attribute tells the browser: "Download this script now, but do not execute it until the entire HTML document has been parsed." This gives you the best of both worlds: the script is in the <head> (clean document structure), but it runs after all HTML is ready.
For learning purposes, placing <script> at the end of <body> is the simplest approach. As you progress, you will transition to using external files with defer in the <head>, which is the industry standard.
Multiple Script Tags
You can have multiple <script> tags in one document. They execute in order, from top to bottom:
<body>
<script>
let message = "Hello";
console.log("Script 1:", message);
</script>
<script>
// This can access 'message' from the previous script
message += ", World!";
console.log("Script 2:", message);
</script>
<script>
console.log("Script 3:", message);
</script>
</body>
Output in console:
Script 1: Hello
Script 2: Hello, World!
Script 3: Hello, World!
All <script> blocks on the same page share the same global scope. A variable declared in one script block is accessible in all subsequent ones.
External JavaScript Files and the src Attribute
While writing JavaScript directly inside <script> tags works, real projects almost always place JavaScript in separate .js files. This approach is cleaner, more maintainable, and enables browser caching.
Linking an External File
Instead of writing code between <script> tags, use the src attribute to point to a JavaScript file:
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>External Script</title>
</head>
<body>
<h1>Hello World Page</h1>
<p id="output"></p>
<script src="script.js"></script>
</body>
</html>
script.js (in the same folder as index.html):
document.getElementById("output").textContent = "Hello from an external file!";
console.log("External script loaded and executed.");
The browser downloads script.js and executes its contents exactly as if that code had been written between the <script> tags.
File Paths for the src Attribute
The src attribute accepts different types of paths:
<!-- Same folder as the HTML file -->
<script src="script.js"></script>
<!-- Inside a subfolder -->
<script src="js/script.js"></script>
<!-- Up one directory, then into a folder -->
<script src="../shared/utils.js"></script>
<!-- Absolute URL (external CDN) -->
<script src="https://cdn.example.com/library.js"></script>
When using src, any code written between the opening and closing tags is ignored:
<!-- The inline code below will NOT run -->
<script src="script.js">
console.log("This is completely ignored!");
</script>
A <script> tag can either load an external file or contain inline code, but never both. If you need both, use two separate <script> tags:
<script src="script.js"></script>
<script>
console.log("This runs after script.js");
</script>
Why External Files Are Better
| Aspect | Inline <script> | External .js File |
|---|---|---|
| Reusability | Duplicated across pages | One file, multiple pages |
| Caching | Re-downloaded every page load | Cached by browser after first load |
| Maintainability | Mixed with HTML | Separated concerns |
| Readability | HTML file gets cluttered | Clean HTML, clean JS |
| Collaboration | Harder to work in teams | Front-end and JS developers work independently |
Loading Multiple External Files
You can load several JavaScript files. They execute in the order they appear:
<body>
<h1>My App</h1>
<script src="utils.js"></script>
<script src="data.js"></script>
<script src="app.js"></script>
</body>
utils.js runs first, then data.js, then app.js. Code in app.js can use variables and functions defined in the earlier files.
console.log(), document.write(), and alert(): When to Use What
JavaScript provides several ways to display output. Each one serves a different purpose, and knowing when to use which will save you confusion.
console.log(): Your Best Friend for Development
console.log() writes a message to the browser's developer console. The message does not appear on the web page itself. You need to open DevTools (F12) to see it.
console.log("Hello, World!");
// Output in console: Hello, World!
console.log(42);
// Output in console: 42
console.log("The answer is", 40 + 2);
// Output in console: The answer is 42
// You can log multiple values separated by commas
let name = "Alice";
let age = 30;
console.log("Name:", name, "Age:", age);
// Output in console: Name: Alice Age: 30
// Objects and arrays are displayed with expandable structure
console.log({ name: "Alice", age: 30 });
// Output in console: {name: 'Alice', age: 30}
console.log([1, 2, 3, 4, 5]);
// Output in console: (5) [1, 2, 3, 4, 5]
When to use console.log():
- Debugging code (checking variable values, tracking execution flow)
- Learning and experimenting
- Logging information during development
- Anytime you want to see a value without disrupting the page
When NOT to use console.log():
- Never leave
console.log()statements in production code that users will see. They clutter the console and can leak sensitive information.
alert(): Modal Dialog Box
alert() displays a popup dialog with a message. The user must click "OK" to dismiss it. While the alert is visible, the user cannot interact with the page at all. The entire page is blocked.
alert("Hello, World!");
This produces a browser-native popup dialog showing "Hello, World!" with an OK button.
alert(100 + 200);
// Shows: 300
alert("Welcome to my website!\nEnjoy your stay.");
// Shows a two-line message (\n creates a new line)
When to use alert():
- Quick debugging when the console is not available
- Very early learning (before you know how to manipulate the page)
- Rare cases where you need to force user acknowledgment
When NOT to use alert():
- Real websites and applications. Alerts are ugly, they block the page, they cannot be styled, and they provide a terrible user experience.
- Debugging. Use
console.log()instead.
alert() is a blocking function. When an alert dialog is open, all JavaScript execution on the page stops completely. No animations run, no timers fire, no network responses are handled. This is why alert() should never be used in production websites.
document.write(): Writing Directly to the Page
document.write() writes content directly into the HTML document at the point where the script runs. The content appears on the web page itself, not in the console.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>document.write Demo</title>
</head>
<body>
<h1>Before the script</h1>
<script>
document.write("<p>Hello from document.write()!</p>");
document.write("<p>I can write <strong>HTML tags</strong> too.</p>");
</script>
<h2>After the script</h2>
</body>
</html>
Result on the page:
Before the script
Hello from document.write()!
I can write HTML tags too.
After the script
The output appears between the <h1> and <h2> because that is where the <script> tag is located in the document.
The dangerous behavior of document.write():
If document.write() is called after the page has finished loading, it erases the entire page:
<body>
<h1>Important content</h1>
<p>This will be destroyed.</p>
<button onclick="document.write('Oops! Everything is gone.')">
Click me
</button>
</body>
Clicking the button replaces the entire page with just the text "Oops! Everything is gone." The heading, paragraph, and button are all destroyed.
Never use document.write() in modern JavaScript. It exists only for historical reasons. If called after the page loads, it destroys all existing content. There are better ways to add content to a page, such as textContent, innerHTML, or DOM manipulation methods you will learn later.
Comparison Table
| Method | Output Location | Blocks Page? | Can Write HTML? | Use In Production? |
|---|---|---|---|---|
console.log() | Developer console | No | No | For debugging only |
alert() | Popup dialog | Yes | No | Almost never |
document.write() | Web page | No* | Yes | Never |
textContent | Web page | No | No (text only) | Yes |
innerHTML | Web page | No | Yes | Yes (with caution) |
*document.write() does not block in the traditional sense, but calling it after page load destroys the document.
The Modern Way: Changing Page Content
Instead of document.write() or alert(), modern JavaScript changes page content by selecting elements and modifying them:
<body>
<p id="output">Waiting...</p>
<script>
// The modern, correct approach
document.getElementById("output").textContent = "Hello, World!";
</script>
</body>
</html>
This changes the text inside the <p> element from "Waiting..." to "Hello, World!" without erasing anything, without blocking the page, and without ugly popups. You will learn these DOM manipulation techniques in depth later in the course.
How Browsers Parse and Execute JavaScript
Understanding what happens behind the scenes when a browser encounters your JavaScript helps you avoid common bugs and write more efficient code.
The Parsing Process Step by Step
When you open an HTML file in a browser, the following sequence occurs:
Step 1: Download the HTML
The browser downloads the HTML file from the server (or reads it from disk if it is a local file).
Step 2: Parse the HTML top to bottom
The browser reads the HTML document from the first line to the last, building the DOM (Document Object Model), a tree-like representation of every element on the page.
Step 3: When a <script> tag is encountered, parsing stops
This is the critical point. By default, when the HTML parser hits a <script> tag:
- HTML parsing pauses
- If it is an external file (
src="..."), the browser downloads the file - The JavaScript code executes
- HTML parsing resumes
Here is a visual timeline:
HTML Parsing: ████████░░░░░░░░████████████
↑ ↑
Script found Script done
Parsing stops Parsing resumes
JS Execution: ████████
Download + Execute
This blocking behavior is exactly why placing scripts at the end of <body> works: by that point, all HTML has already been parsed into the DOM.
The defer and async Attributes
Modern JavaScript provides two attributes to control how external scripts load:
defer: Download the script in parallel while HTML continues parsing. Execute the script only after the HTML is fully parsed.
<head>
<script src="app.js" defer></script>
</head>
HTML Parsing: ████████████████████████████
↑
JS Download: ██████████ Execute script
(after parsing)
async: Download the script in parallel, but execute it immediately when the download finishes, pausing HTML parsing at that moment.
<head>
<script src="analytics.js" async></script>
</head>
HTML Parsing: ████████████░░░░████████████
↑
JS Download: ██████████ Execute immediately
(pauses parsing)
When to use each:
| Attribute | Execution Order | Waits for DOM? | Best For |
|---|---|---|---|
| (none) | In order | No | Legacy code |
defer | In order | Yes | Your main application scripts |
async | Whichever finishes first | No | Independent scripts (analytics, ads) |
The defer and async attributes only work with external scripts (those using the src attribute). They have no effect on inline <script> blocks.
Why This Matters for Beginners
The most common beginner error is trying to access an HTML element before it exists:
<!-- WRONG: Script runs before the button exists -->
<head>
<script>
let btn = document.getElementById("myButton");
btn.addEventListener("click", function() { // Error! btn is null
alert("Clicked!");
});
</script>
</head>
<body>
<button id="myButton">Click Me</button>
</body>
Three ways to fix this:
<!-- Fix 1: Move script to end of body -->
<body>
<button id="myButton">Click Me</button>
<script src="app.js"></script>
</body>
<!-- Fix 2: Use defer -->
<head>
<script src="app.js" defer></script>
</head>
<body>
<button id="myButton">Click Me</button>
</body>
<!-- Fix 3: Wait for DOMContentLoaded event (you'll learn this later) -->
<head>
<script>
document.addEventListener("DOMContentLoaded", function() {
let btn = document.getElementById("myButton");
btn.addEventListener("click", function() {
alert("Clicked!");
});
});
</script>
</head>
<body>
<button id="myButton">Click Me</button>
</body>
For now, use Fix 1 (script at end of body). It is the simplest and most reliable approach while you are learning.
Exercise: Build a Hello World Page with Three Output Methods
Time to put everything together. You will create a complete page that uses console.log(), alert(), and DOM manipulation to display "Hello, World!" in three different ways simultaneously.
Step 1: Create the Project Structure
Create a new folder called hello-world with two files:
hello-world/
├── index.html
└── script.js
Step 2: Write the HTML
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! (in three ways)</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 600px;
margin: 50px auto;
padding: 0 20px;
}
.output-box {
background-color: #f4f4f4;
border: 2px solid #333;
border-radius: 8px;
padding: 20px;
margin: 20px 0;
font-size: 1.2em;
}
.method-label {
color: #666;
font-size: 0.8em;
text-transform: uppercase;
letter-spacing: 1px;
}
#timestamp {
color: #888;
font-size: 0.9em;
}
</style>
</head>
<body>
<h1>Hello, World! (in three ways)</h1>
<p class="method-label">Method 1: alert() -> Check the popup dialog</p>
<p class="method-label">Method 2: console.log() -> Open DevTools (F12) to see the console</p>
<div class="output-box">
<p class="method-label">Method 3: DOM Manipulation -> See below:</p>
<p id="greeting">Waiting for JavaScript...</p>
<p id="timestamp"></p>
</div>
<script src="script.js"></script>
</body>
</html>
Step 3: Write the JavaScript
script.js:
// ============================================
// METHOD 1: alert()
// Shows a popup dialog: the user must click OK
// ============================================
alert("Hello, World! (from alert)");
// ============================================
// METHOD 2: console.log()
// Outputs to the browser's developer console
// Open DevTools with F12 to see this
// ============================================
console.log("Hello, World! (from console.log)");
console.log("You can log multiple things:");
console.log("- Strings:", "Hello!");
console.log("- Numbers:", 42);
console.log("- Booleans:", true);
console.log("- Objects:", { method: "console.log", works: true });
// ============================================
// METHOD 3: DOM Manipulation
// Changes the content of an HTML element
// This is the modern, correct approach
// ============================================
document.getElementById("greeting").textContent =
"Hello, World! (from DOM manipulation)";
// Bonus: show the current date and time
let now = new Date();
document.getElementById("timestamp").textContent =
"Page loaded at: " + now.toLocaleTimeString();
Step 4: Run It
Option A (using Live Server): Right-click index.html in VS Code and select "Open with Live Server."
Option B (without Live Server): Double-click index.html in your file explorer to open it directly in the browser.
What You Should See
- First: An alert popup appears saying "Hello, World! (from alert)." Click OK to dismiss it.
- On the page: The output box displays "Hello, World! (from DOM manipulation)" with the current time.
- In the console (press F12): Multiple log messages appear, including the "Hello, World!" message and examples of logging different data types.
Challenge: Extend It
Try modifying script.js to add these features:
// Challenge 1: Ask the user's name and greet them
let userName = prompt("What is your name?");
if (userName) {
document.getElementById("greeting").textContent =
"Hello, " + userName + "! Welcome to JavaScript.";
console.log("User entered their name:", userName);
} else {
document.getElementById("greeting").textContent =
"Hello, mysterious stranger!";
console.log("User did not enter a name.");
}
// Challenge 2: Add a second paragraph dynamically
let newParagraph = document.createElement("p");
newParagraph.textContent = "This paragraph was created entirely by JavaScript!";
document.body.appendChild(newParagraph);
Do not worry if the DOM manipulation code (createElement, appendChild) looks unfamiliar. You will learn these methods in detail later. For now, just notice how JavaScript can create and modify page content dynamically.
Summary
You have just learned the fundamentals of running JavaScript in the browser:
- The
<script>tag embeds JavaScript in HTML, and its placement matters. Place it at the end of<body>or usedeferin the<head>. - External
.jsfiles are the standard approach. They keep code organized, enable caching, and separate concerns. - A
<script>tag uses eithersrcfor an external file or inline code, but never both at the same time. console.log()is your primary debugging tool and outputs to the developer console.alert()creates a blocking popup dialog. Avoid it in real applications.document.write()is a legacy method that can destroy your page. Never use it in modern code.- Browsers parse HTML top to bottom and pause at each
<script>tag by default. Thedeferattribute solves this by delaying script execution until the DOM is ready. - The modern way to display output is through DOM manipulation: selecting elements and changing their content.
With these building blocks in place, you are ready to dive into JavaScript's code structure and syntax rules, where you will learn how the language interprets your code and the conventions that keep it readable and error-free.