|

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

MethodDescriptionRecommended?
External FileLink to a .js file with <script src="...">✅ Best practice
Internal (Embedded)Write JS inside <script> tags in HTML✅ For page-specific code
Inline HandlersWrite JS in HTML attributes like onclick=""❌ Not recommended

a. Adding JavaScript to HTML

Two primary ways:

  1. Embedding JavaScript in the <head> or <body> section using <script> tags
  2. 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

BenefitDescription
ReusabilityOne file can be used by multiple HTML pages
CachingBrowser caches the file — faster page loads
Separation of ConcernsHTML for structure, JS for behavior
MaintainabilityEasier to find and edit code
PerformanceCan be loaded asynchronously

The defer and async Attributes

AttributeBehaviorWhen to Use
deferDownloads in parallel, executes after HTML parsing, preserves order✅ Recommended for most scripts
asyncDownloads in parallel, executes as soon as ready, order not guaranteedFor 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 CaseWhy
Single-page scriptsOnly used on one page
Quick prototypingFast to set up
Page-specific codeNot needed elsewhere
Critical inline scriptsMust 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

ProblemDescription
Mixes concernsHTML and JS should be separate
Hard to maintainLogic scattered across HTML
No reusabilityCan’t be cached or reused
Debugging difficultyErrors are harder to trace
CSP violationsFails strict Content Security Policy
Global scope pollutionFunctions 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:

AspectInline HandleraddEventListener()
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:

  1. Create both files in the same folder
  2. Open index.html in a browser
  3. Click each button to see the output
  4. Press F12 to open the console and see the log messages

Method Comparison

AspectExternalInternalInline
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 forProductionPage-specificQuick tests only

Quick Reference

MethodSyntaxWhen to Use
External<script src="file.js" defer></script>✅ Production code
Internal<script>...</script>Page-specific scripts
Inlineonclick="func()"❌ Avoid (quick tests only)

Script Loading Attributes

AttributeBehaviorUse Case
deferExecutes after HTML parsing, preserves order✅ Most scripts
asyncExecutes when ready, order not guaranteedIndependent 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!