JavaScript 2 🧬 How to add JavaScript
There are three ways to add JavaScript to an HTML document. This chapter covers all three — and explains when to use each.
Overview of Methods
| Method | Description | Recommended? |
|---|---|---|
| External File | Link to a .js file with <script src="..."> | ✅ Best practice |
| Internal (Embedded) | Write JS inside <script> tags in HTML | ✅ For page-specific code |
| Inline Handlers | Write JS in HTML attributes like onclick="" | ❌ Not recommended |
a. Adding JavaScript to HTML
Two primary ways:
- Embedding JavaScript in the
<head>or<body>section using<script>tags - Linking to an external JavaScript file using
<script src="...">
You may also find inline handlers like onclick="showSomething()" in HTML elements — but this is not recommended. Instead, it’s better to use addEventListener() in JavaScript.
Key Point: Placing JavaScript in the <body> section (at the end) ensures the code runs after all HTML is parsed.
1. External JavaScript (Recommended)
Link to an external .js file using the src attribute.
HTML file (index.html):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>External JavaScript</title>
<script src="myScript.js" defer></script>
</head>
<body>
<button id="greetBtn">Click me!</button>
</body>
</html>
JavaScript file (myScript.js):
function greet() {
alert('Hello, world!');
}
document.getElementById('greetBtn').addEventListener('click', greet);
Benefits
| Benefit | Description |
|---|---|
| Reusability | One file can be used by multiple HTML pages |
| Caching | Browser caches the file — faster page loads |
| Separation of Concerns | HTML for structure, JS for behavior |
| Maintainability | Easier to find and edit code |
| Performance | Can be loaded asynchronously |
The defer and async Attributes
| Attribute | Behavior | When to Use |
|---|---|---|
defer | Downloads in parallel, executes after HTML parsing, preserves order | ✅ Recommended for most scripts |
async | Downloads in parallel, executes as soon as ready, order not guaranteed | For independent scripts (analytics) |
| (none) | Downloads and executes immediately, blocks HTML parsing | ❌ Avoid in <head> |
<!-- Deferred — runs after HTML is parsed -->
<script src="app.js" defer></script>
<!-- Async — runs as soon as downloaded -->
<script src="analytics.js" async></script>
<!-- No attribute — blocks HTML parsing -->
<script src="blocking.js"></script>
Visual comparison:
Without defer/async (blocking):
HTML parsing ────[STOP ]──Download JS──Execute JS──[RESUME ]────
With defer:
HTML parsing ──────────────────────────────────[Execute JS ]
JS download ────────(parallel)───────
With async:
HTML parsing ────[STOP ]──[Execute JS ]──[RESUME ]────
JS download ────(parallel)────
2. Internal (Embedded) JavaScript
Write JavaScript directly inside <script> tags in the HTML file.
In the <head>:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Internal JavaScript</title>
<script>
function greet() {
alert('Hello, world!');
}
</script>
</head>
<body>
<button onclick="greet()">Click me!</button>
</body>
</html>
At the end of <body> (recommended placement):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Internal JavaScript</title>
</head>
<body>
<button id="greetBtn">Click me!</button>
<script>
function greet() {
alert('Hello, world!');
}
document.getElementById('greetBtn').addEventListener('click', greet);
</script>
</body>
</html>
When to Use Internal JavaScript
| Use Case | Why |
|---|---|
| Single-page scripts | Only used on one page |
| Quick prototyping | Fast to set up |
| Page-specific code | Not needed elsewhere |
| Critical inline scripts | Must run before external file loads |
3. Inline JavaScript Handlers (Not Recommended)
Write JavaScript directly in HTML attributes.
<button onclick="alert('Hello!')">Click me!</button>
<button onclick="greet()">Click me!</button>
<a href="#" onclick="return false;">Link</a>
<img src="image.jpg" onmouseover="this.src='hover.jpg'" onmouseout="this.src='image.jpg'">
Why It’s Not Recommended
| Problem | Description |
|---|---|
| Mixes concerns | HTML and JS should be separate |
| Hard to maintain | Logic scattered across HTML |
| No reusability | Can’t be cached or reused |
| Debugging difficulty | Errors are harder to trace |
| CSP violations | Fails strict Content Security Policy |
| Global scope pollution | Functions become global by default |
The Better Way: addEventListener()
<!-- HTML — clean, no JS -->
<button id="greetBtn">Click me!</button>
// JavaScript — separate, clean
document.getElementById('greetBtn').addEventListener('click', function() {
alert('Hello, world!');
});
Comparison:
| Aspect | Inline Handler | addEventListener() |
|---|---|---|
| Separation | ❌ Mixed | ✅ Clean |
| Multiple handlers | ❌ Only one | ✅ Multiple |
| Removable | ❌ Hard | ✅ Easy |
| Reusable | ❌ No | ✅ Yes |
| CSP-friendly | ❌ No | ✅ Yes |
Complete Example
Here’s a complete example demonstrating all three methods:
HTML file (index.html):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>How to Add JavaScript</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
background: #f8f9fa;
color: #333;
line-height: 1.6;
}
h1 { color: #007bff; border-bottom: 3px solid #007bff; padding-bottom: 10px; }
h2 { color: #28a745; border-left: 4px solid #28a745; padding-left: 15px; margin-top: 30px; }
.demo-box {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
margin: 15px 0;
}
button {
padding: 12px 24px;
background: #007bff;
color: white;
border: none;
border-radius: 8px;
font-size: 1em;
font-weight: bold;
cursor: pointer;
margin: 5px;
transition: all 0.3s;
}
button:hover {
background: #0056b3;
transform: translateY(-2px);
box-shadow: 0 4px 15px rgba(0, 123, 255, 0.3);
}
.method-badge {
display: inline-block;
padding: 3px 10px;
border-radius: 20px;
font-size: 0.75rem;
font-weight: bold;
color: white;
margin-left: 10px;
}
.badge-external { background: #28a745; }
.badge-internal { background: #ffc107; color: #333; }
.badge-inline { background: #dc3545; }
#output {
background: #e9ecef;
padding: 15px;
border-radius: 8px;
margin-top: 15px;
min-height: 40px;
font-family: 'Courier New', monospace;
border-left: 4px solid #007bff;
}
</style>
</head>
<body>
<h1>How to Add JavaScript</h1>
<div class="demo-box">
<h2>1. External JavaScript <span class="method-badge badge-external">Recommended</span></h2>
<p>Loaded from an external <code>.js</code> file with <code>defer</code>.</p>
<button id="externalBtn">External JS</button>
<div id="output">Click the button to see output...</div>
</div>
<div class="demo-box">
<h2>2. Internal JavaScript <span class="method-badge badge-internal">OK</span></h2>
<p>Written inside <code><script></code> tags at the end of <code><body></code>.</p>
<button id="internalBtn">Internal JS</button>
</div>
<div class="demo-box">
<h2>3. Inline Handler <span class="method-badge badge-inline">Not Recommended</span></h2>
<p>Written directly in the HTML attribute (avoid this in production).</p>
<button onclick="inlineHandler()">Inline JS</button>
</div>
<!-- Internal JavaScript — placed at end of body -->
<script>
// Internal JavaScript
document.getElementById('internalBtn').addEventListener('click', function() {
const output = document.getElementById('output');
output.textContent = '✅ Internal JavaScript executed!';
output.style.borderLeftColor = '#ffc107';
});
// Inline handler function (still defined in script, but called from HTML)
function inlineHandler() {
const output = document.getElementById('output');
output.textContent = '⚠️ Inline handler executed — but not recommended!';
output.style.borderLeftColor = '#dc3545';
}
console.log('Internal script loaded and running.');
</script>
<!-- External JavaScript -->
<script src="external.js" defer></script>
</body>
</html>
External JavaScript file (external.js):
// External JavaScript
document.getElementById('externalBtn').addEventListener('click', function() {
const output = document.getElementById('output');
output.textContent = '✅ External JavaScript executed!';
output.style.borderLeftColor = '#28a745';
});
console.log('External script loaded and running.');
How to test:
- Create both files in the same folder
- Open
index.htmlin a browser - Click each button to see the output
- Press
F12to open the console and see the log messages
Method Comparison
| Aspect | External | Internal | Inline |
|---|---|---|---|
| Separation of concerns | ✅ Excellent | ✅ Good | ❌ Poor |
| Reusability | ✅ Multiple pages | ❌ Single page | ❌ Single element |
| Caching | ✅ Browser caches | ❌ No caching | ❌ No caching |
| Maintainability | ✅ Easy | ⚠️ Medium | ❌ Hard |
| Performance | ✅ Best (with defer/async) | ⚠️ OK | ❌ Worst |
| CSP-friendly | ✅ Yes | ⚠️ Sometimes | ❌ No |
| Recommended for | Production | Page-specific | Quick tests only |
Quick Reference
| Method | Syntax | When to Use |
|---|---|---|
| External | <script src="file.js" defer></script> | ✅ Production code |
| Internal | <script>...</script> | Page-specific scripts |
| Inline | onclick="func()" | ❌ Avoid (quick tests only) |
Script Loading Attributes
| Attribute | Behavior | Use Case |
|---|---|---|
defer | Executes after HTML parsing, preserves order | ✅ Most scripts |
async | Executes when ready, order not guaranteed | Independent scripts |
| (none) | Blocks HTML parsing | ❌ Avoid in <head> |
<!-- Best practice: defer in head -->
<script src="app.js" defer></script>
<!-- Or place at end of body -->
<body>
<!-- content -->
<script src="app.js"></script>
</body>
Best Practices
✅ Do This:
<!-- External file with defer -->
<script src="app.js" defer></script>
<!-- Or at end of body -->
<body>
<button id="btn">Click</button>
<script src="app.js"></script>
</body>
// Use addEventListener (not onclick)
document.getElementById('btn').addEventListener('click', handler);
❌ Don’t Do This:
<!-- Don't use inline handlers -->
<button onclick="doSomething()">Click</button>
<!-- Don't block HTML parsing -->
<head>
<script src="app.js"></script> <!-- Blocks parsing! -->
</head>
<!-- Don't put scripts before HTML elements they reference -->
<head>
<script>
document.getElementById('btn'); // null — not parsed yet!
</script>
</head>
<body>
<button id="btn">Click</button>
</body>
Pro Tip: Use external JavaScript with defer for production code — it’s the cleanest, fastest, and most maintainable approach. Use internal JavaScript only for page-specific code. Avoid inline handlers entirely — they mix concerns, are hard to maintain, and fail strict Content Security Policies. Always prefer addEventListener() over onclick attributes for cleaner, more flexible event handling.
Stop using slow, ad-bloated tool sites! 🤮
🔎 Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)
⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free
🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!