JS Where To
In this page:
Inline JavaScript
Inline JavaScript is written directly inside an HTML element's attribute, such as onclick, running only when that specific event happens on that specific element.
Note: Inline JavaScript is fine for tiny, one-off demos, but should be avoided in real applications in favor of separating structure from behavior.
Warning: Inline event handlers mix HTML and JavaScript together, making the code harder to read, reuse, and debug as a project grows.
Example: Inline JavaScript
<button onclick="console.log('Button clicked')">Click Me</button>
Internal Script Tag
An internal script tag places JavaScript inside the HTML document itself, wrapped in <script></script>, keeping the code separate from individual elements while still living in the same file.
Note: Internal scripts are useful for quick prototypes or single-page demos where creating a separate file feels unnecessary.
Warning: Internal scripts cannot be reused across multiple pages the way an external file can, leading to duplicated code in larger sites.
Example: Internal Script Tag
<script>
console.log("Running from an internal script tag.");
</script>
External JavaScript Files
An external file keeps all JavaScript in its own .js file, linked into the HTML page with a script tag's src attribute, which keeps HTML clean and lets multiple pages share the exact same code.
Note: Name external files descriptively, like main.js or validation.js, so their purpose is clear at a glance across a whole project.
Warning: The browser cannot run an external script until it successfully downloads the file, a broken path silently means the script never runs.
Example: External JavaScript Files
<script src="main.js"></script>
Head vs Body Placement
A script placed in the head runs before the browser has parsed the body, which can cause errors if it tries to access elements that don't exist yet, while a script placed just before the closing body tag runs after all HTML above it has already loaded.
Note: As a simple rule for beginners, place your script tag right before </body> unless you have a specific reason to load it earlier.
Warning: A script in the head that directly manipulates body elements without waiting for them will fail, since those elements are not yet part of the page.
Example: Head vs Body Placement
<head>
<script>
console.log(document.body); // null - body not parsed yet
</script>
</head>
<body>
<p>Content</p>
</body>
The defer and async Attributes
defer tells the browser to download the script in the background and run it only after the whole page has been parsed, in order, while async downloads in the background and runs the script as soon as it's ready, regardless of parsing order.
Note: Use defer for scripts that need the full page structure to exist, and async for independent scripts, like analytics, that don't depend on other content.
Warning: Multiple async scripts can run in any order relative to each other, which can cause bugs if one script secretly depends on another.
Example: The defer and async Attributes
<script src="main.js" defer></script>
<script src="analytics.js" async></script>
- Writing large amounts of JavaScript inline on HTML elements, which becomes very hard to read and maintain as a page grows.
- Placing a script tag before the elements it needs to access without deferring it, causing errors because those elements don't exist yet.
- Forgetting the src attribute points to the correct relative or absolute path when linking an external JavaScript file.
- JavaScript can live inline on an element, inside an internal <script> tag, or in an external linked file.
- External files are the most maintainable approach for real projects, since the same file can be reused across many pages.
- The defer and async attributes control when an external script actually executes relative to page parsing.
All three placement methods, inline, internal, and external scripts, along with defer and async attributes, are supported by every modern browser.
Chapter Quiz — Complete all 12 topics to unlock
0/12 topics done
Complete these topics first: