Click a button on a website. Something changes. A menu opens or a message pops up. That’s how JavaScript works.
Table of Content
- How JavaScript Loads in a Web Page
- How
defer
andasync
Load External JavaScript Files - Understand How the JavaScript Engine Works
- Understanding the JavaScript Event Loop
- Web APIs and the Browser Environment
- Synchronous vs. Asynchronous Code in the Browser
- JavaScript Security in the Browser Context
- Developer Tools to See JavaScript in Action
- Wrapping Up
- FAQ’s
It runs right inside your browser. Fast. Quiet. Behind the scenes.
But how does it know what to do? How does your browser read the code and make things happen?
This article will show you simple steps and explain how JavaScript runs your code.
How JavaScript Loads in a Web Page
The browser reads the HTML first when it loads a web page. If it finds a <script>
tag, it knows there’s JavaScript to load.
Here is an example:
<script src="script.js"></script>
This tells the browser to fetch and run the file script.js
.
Also, you can write JavaScript inside the HTML file:
<!DOCTYPE html>
<html>
<head>
<title>My Page</title>
<script>
console.log("The script is loaded!");
</script>
</head>
<body>
</body>
</html>
This script runs as the browser reads the <head>
section. It will fail if it tries to access DOM elements before they load.
You can also place it on the page:
- In the
<head>
can block page loading. - At the end of
<body>
the common for better performance. It ensures HTML loads first.
There are two attributes to load external JavaScript files fast in the browser. Let’s take a look at each one in the following section.
How defer
and async
Load External JavaScript Files
Both defer
and async
are attributes for the <script>
tag. They help control how external JavaScript files load and run.
Here is each one in-depth:
The defer
Attribute:
- Loads the script while it parses HTML.
- Runs the script after the HTML is fully parsed.
- Good for most scripts that interact with the DOM.
Here is an example:
<script src="script.js" defer></script>
The async
Attribute:
- Loads and runs the script as soon as it’s ready.
- Doesn’t wait for HTML to finish parsing.
- Can run out of order if you have multiple scripts.
For example:
<script src="script.js" async></script>
Here are the key points for each one:
Method | Blocks HTML? | Waits for HTML? | Use Case |
---|---|---|---|
Normal script | Yes | No | Legacy/default |
defer | No | Yes | Safe for DOM use |
async | No | No | Fast, but order not guaranteed |
You understood how the browser reads and loads the JavaScript code into the stack. But did you ever ask yourself what happens behind the scenes? Let’s move on to the next section to answer this question.
Understand How the JavaScript Engine Works
Here are the steps of what happens when you write JavaScript code in the page:

1- Parse HTML:
The browser (Chrome, Firefox, etc.) receives HTML as plain text from the server.
- The browser has an HTML parser.
- It reads HTML line-by-line from top to bottom.
- It builds a DOM Tree while reading — a tree-like structure where every HTML element becomes a node.
For example:
<!DOCTYPE html>
<html>
<head>
<title>FlatCoding: How Does JavaScript Work to Run Code in the Web Browser</title>
<script src="script.js"></script>
</head>
<body>
<h1>FlatCoding Tutorials</h1>
<p>This is a Paragraph Text.</p>
</body>
</html>
It becomes a DOM element, like this:

- It continues the parsing and does not stop if there’s no script tag yet.
- It tries to render what it can while it is building the DOM.
2- Script Tag Encountered:
When the browser’s parser sees a <script>
tag.
If the browser’s parser sees a <script>
it checks if it’s an inline script (<script>console.log('hi')</script>
) or external script (<script src="script.js"></script>
), the parser pauses immediately.
It must fetch the JavaScript file if it’s external:
- The browser sends an HTTP request to get
script.js
. - It waits for the script to completely download.
Then, the browser executes the script immediately and continues the parsing of HTML only after it runs the script.
3- Downloading and Caching the Script:
The browser first checks the HTTP cache when it fetches an external script. If it finds a recently downloaded copy, it uses that version.
The browser requests it from the server if the file is not in the cache. The browser places it in memory and prepares it for execution after downloading the script.
4- JavaScript Parsing in the Engine:
It sends the code into the JavaScript engine, such as V8 in Chrome, after the browser fetches the script.
Tokenization:
The first step is tokenization, also called lexical analysis. The engine breaks the code into small pieces called tokens, which include keywords, brackets, variables, and operators.
For example:
The line var x = 5;
breaks into tokens: var
, x
, =
, 5
, and ;
.
Syntax Parsing:
The engine analyzes the tokens based on JavaScript grammar rules. It creates an Abstract Syntax Tree (AST), which is a large object that represents the structure of the program.
For example:
An assignment like var x = 5;
turns into a tree structure that shows a “Variable Declaration.”.
5- Compilation to Machine Code:
Modern JavaScript engines apply JIT (Just-In-Time) Compilation to improve performance.
It usually converts AST to Intermediate Representation (IR) first, then optimizes and compiles into machine code. Bytecode is part of the interpreter path, not direct machine code compilation in JIT.
JIT Compilation allows JavaScript to run much faster than older versions that only interpreted the code.
6- Call Stack and Memory Management (the execution)
The engine runs it. It handles memory allocation when it stores variables and functions. Primitives such as numbers and strings go into the Stack.
Larger structures like objects, arrays, and functions are placed in the Heap, a bigger memory area.
The engine also manages function calls using a Call Stack. When a function is called, the engine pushes it onto the stack.
Once the function finishes, it pops the function off. If too many functions pile up without being completed, the engine throws a Stack Overflow Error.
7- Garbage Collection
When an object or variable no longer remains reachable, the JavaScript engine removes it automatically.
This cleanup happens through a Garbage Collector. The collector finds unreachable objects and frees their memory.
Different browsers use different algorithms, such as Mark-and-Sweep, to handle this process. Garbage collection helps prevent memory from filling up unnecessarily.
8- Painting the Page (Render Tree)
After JavaScript execution ends, the browser updates the content the user sees. It builds a Render Tree by combining the DOM and CSS.
Once the tree is ready, the browser paints pixels on the screen. Heavy JavaScript can delay this painting step, which causes slower page loading.
Let’s move on to the following section to take a look at the JavaScript Event Loop.
Understanding the JavaScript Event Loop
The JavaScript Event Loop is the mechanism that makes JavaScript handle tasks like:
- User clicks
- Server requests
- Timers
Even though JavaScript itself runs one task at a time (it’s single-threaded). Here’s how it works at a basic level:
- Call Stack:
- Where JavaScript keeps track of what functions are running.
- It runs one function at a time, top to bottom.
- It stacks it on top if a function calls another.
- Web APIs (in browsers) or Node APIs (in Node.js):
- These handle things that take time, like
setTimeout
orfetch()
. Or likeDOM events
. - They run outside the main thread.
- These handle things that take time, like
- Task Queue / Callback Queue:
- Its callback gets pushed here when an async task finishes (like after a timer or server response).
- The queue holds these tasks until the stack is empty.
- Event Loop:
- It constantly checks:
- “Is the call stack empty?”
- It pulls the first task from the queue and runs it if yes.
- This is why a
setTimeout
with0ms
delay still waits until the stack is clear.
- It constantly checks:
Here is an example:
console.log('Start the javascript code.'); //<== Start Log
setTimeout(() => {
console.log('log of timeout callback here.');
}, 0);
console.log('End the javascript code.'); //<== End Log
Here is the output:
Start the javascript code.
End the javascript code.
log of timeout callback here.
Even though setTimeout
has 0ms
, JavaScript finishes the start
and end
logs first because the event loop waits for the stack to be empty.
The Event Loop lets JavaScript handle multiple things without stopping your page, even though it can run only one function at a time.
Let’s move on to the following section to understand the browser environment and web APIs.
Web APIs and the Browser Environment
JavaScript by itself can only do basic stuff: math, loops, logic. It cannot handle things like timers, HTTP requests, or the DOM on its own. That’s where the browser environment comes in.
The browser (like Chrome, Firefox, Safari) gives JavaScript extra tools called Web APIs. These tools are outside of JavaScript but work with it.
Here are some common web APIs:
Web API | What It Does |
---|---|
setTimeout | Runs code after a delay |
DOM | Lets you read or change HTML elements |
fetch | Lets you make network requests (like getting data from a server) |
console.log | Shows messages in the console |
addEventListener | Watches for events like clicks or keypresses |
Let’s move on to the following section to understand the difference between synchronous and asynchronous Code.
Synchronous vs. Asynchronous Code in the Browser
Synchronous code runs one line at a time, in order. Each task must finish before the next one starts. JavaScript naturally runs synchronously. It blocks everything after it if one task is slow.
Here is an example:
console.log('Start js code');
for (let i = 0; i < 1e9; i++) {
// Simulating heavy work
}
console.log('End js code');
The output:
Start js code
End js code
Here, it prints “Start js code” and freezes (big loop), then prints the “End js code”.
If something takes long (like reading a file, waiting for a server), it freezes the page!
Asynchronous code starts a task and keeps going without waiting for it to finish. The slow task finishes in the background, and when ready, it calls back. This makes the browser fast and responsive.
Here is an example:
console.log('Start js code');
setTimeout(() => {
console.log('when timeout done');
}, 2000);
console.log('End js code');
Output:
Start js code
End js code
when timeout done
Here are common ways:
Method | How It Works |
---|---|
setTimeout , setInterval | Run code after a delay or repeatedly |
Event Listeners | Wait for events like clicks or keypresses |
fetch API | Get data from servers without blocking |
Promises | Cleaner way to handle future values |
async/await | Makes asynchronous code look synchronous |
Let’s move on to the following part to see how JavaScript secures the context of the browser.
JavaScript Security in the Browser Context
JavaScript runs inside the browser, but it must stay secure. Browsers and developers use several methods to protect users and data:
Same-Origin Policy (SOP):
- Browsers block JavaScript from accessing data across different domains.
- A script from
example.com
can’t read data fromanother-site.com
. - This stops many attacks.
Cross-Origin Resource Sharing (CORS):
- Sometimes, sites need to share data safely.
- CORS is a rule system that tells browsers when cross-origin access is allowed.
Content Security Policy (CSP):
- CSP lets websites tell browsers what scripts can run.
- It blocks untrusted or injected scripts, reducing XSS (Cross-Site Scripting) attacks.
Secure JavaScript APIs:
- Modern APIs (like
fetch
,postMessage
, Web Storage) add security features. - Example:
postMessage
allows safe messaging between different origins, but it checks the target origin.
Sandboxing:
- Browsers isolate tabs, iframes, and even scripts.
- Sandboxed iframes can’t run unsafe code or access the parent page.
Strict Mode:
"use strict"
in JavaScript makes it easier to catch errors and avoid unsafe actions (like using undeclared variables).
Secure Handling of User Input:
- Developers sanitize and validate all user input to stop XSS, SQL injection, and other attacks.
- Never trust raw input inside the DOM without cleaning it.
HTTPS:
Browsers enforce secure connections (HTTPS) to prevent data leaks and script tampering over networks.
All of these methods help keep JavaScript safe. But how can you actually see what JavaScript does in the browser?
Let’s look at the tools developers use to watch JavaScript in action:
Developer Tools to See JavaScript in Action
Browsers have built-in tools that help you inspect, debug, and understand JavaScript:
Console:
- Shows errors, warnings, and logs.
- You can run JavaScript commands directly.
- Helps debug by printing variable values and checking app behavior.
Sources Panel:
- Lets you view all loaded JavaScript files.
- You can set breakpoints to pause code and see what’s happening step-by-step.
- Shows call stacks and variable values when paused.
Network Panel:
- Shows network requests (like API calls).
- Helps track JavaScript-triggered requests and see response data.
- Useful to debug fetch, AJAX, and third-party API usage.
Performance Panel:
- Records app performance.
- You can see how JavaScript impacts page load and runtime.
- Helps find slow scripts and optimize them.
Memory Panel:
- Tracks memory usage over time.
- Helps detect memory leaks caused by JavaScript holding onto unused objects.
Application Panel:
- Shows storage used by JavaScript, like LocalStorage, SessionStorage, and IndexedDB.
- Also manages service workers and cached assets.
Debugger:
- Works inside the Sources panel.
- Lets you pause, step through, and inspect code line-by-line.
- Helps find logic errors and understand flow.
Wrapping Up
In this article, you learned how JavaScript loads, runs, and interacts with the browser, and how security measures protect users and data.
Here is a quick recap:
- JavaScript loads through
<script>
tags and can block or defer page loading. - The JavaScript engine parses, compiles, and executes code using the call stack and memory management.
- The Event Loop handles asynchronous tasks without freezing the page.
- Web APIs extend JavaScript’s power by allowing timers, HTTP requests, and DOM manipulation.
- Security features like SOP, CORS, CSP, sandboxing, and HTTPS keep JavaScript safe in the browser.
- Developer tools like Console, Sources, Network, and Debugger panels help you inspect and troubleshoot JavaScript behavior.