Chapter 2 Beginner 22 min min read Updated 2026-04-09

JavaScript in the Browser - Script Tags and Console

Practice Questions →

In This Chapter

What Is It?

What Are Script Tags and the Browser Console?

In the previous chapter, you learned that JavaScript adds interactivity to web pages. But how exactly do you connect JavaScript code to your HTML page? That is where the <script> tag comes in.

The <script> tag tells the browser: "Hey, the code inside this tag is JavaScript. Please run it." Without this tag, the browser would treat your JavaScript code as plain text and display it on the page instead of executing it.

The browser console is a built-in tool in every modern browser that lets you see JavaScript output, test code snippets, and debug errors. Think of it as a scratchpad where you can experiment with JavaScript in real time. Open it by pressing F12 (or Ctrl+Shift+J on Chrome) and clicking the Console tab.

Why Does It Matter?

Why Do Script Tags and the Console Matter?

Understanding how to properly add JavaScript to HTML and how to use the browser console are foundational skills that everything else builds on.

1. Script Placement Affects Whether Your Code Works

If you put your script in the wrong place, your JavaScript can fail silently — the page loads fine but nothing happens. Understanding where to place script tags and how script loading works prevents hours of frustration.

2. The Console Is Your Debugging Lifeline

When something goes wrong in your JavaScript (and it will), the console shows you the error message, the file name, and even the exact line number. Without the console, debugging would be like trying to find a typo in a book with your eyes closed.

3. console.log Is Your Best Learning Tool

As you learn JavaScript, you will constantly use console.log() to check values, test expressions, and understand what your code is doing at each step. Professional developers use it daily too. Mastering the console early makes every future chapter easier.

4. External Scripts Are Industry Standard

Real websites never put thousands of lines of JavaScript directly in their HTML files. They use external .js files linked with <script src="...">. Understanding this pattern is essential for building real projects.

Detailed Explanation

Detailed Explanation

1. Three Ways to Add JavaScript to HTML

There are three methods to include JavaScript in an HTML page:

Method 1: Inline Script (Inside the HTML)

Write JavaScript directly between <script> and </script> tags in your HTML file. This is the simplest method and good for small scripts or learning.

<script>
  console.log("This is inline JavaScript");
</script>

Method 2: External Script File

Write your JavaScript in a separate .js file and link it using the src attribute. This is the preferred method for real projects because it keeps your HTML clean and your JavaScript organized.

<!-- In your HTML file -->
<script src="script.js"></script>

<!-- In a file called script.js -->
console.log("This is from an external file");

Important rule: When a <script> tag has a src attribute, any code between the opening and closing tags is ignored. You cannot mix both methods in one tag.

Method 3: Inline Event Handlers

Write JavaScript directly in HTML attributes like onclick, onmouseover, etc. This should only be used for very simple one-line actions, not for real projects.

<button onclick="alert('Clicked!')">Click Me</button>

2. Where to Place Script Tags

The placement of your script tag matters a lot. Here are the three options:

Option A: In the <head> (Usually Bad)

When the browser encounters a <script> tag in the <head>, it stops building the page, downloads and runs the script, and only then continues with the rest of the HTML. If your script tries to access HTML elements that have not been created yet, it will fail.

Option B: Before </body> (Traditional Best Practice)

Placing the script just before the closing </body> tag means all HTML elements are already created when the script runs. This was the standard approach for years.

Option C: In <head> with defer (Modern Best Practice)

The defer attribute tells the browser: "Download this script in the background, but do not run it until the entire HTML page is fully loaded." This gives you the best of both worlds — the script starts downloading early but runs after the page is ready.

<head>
  <script src="script.js" defer></script>
</head>

There is also the async attribute, which downloads the script in the background and runs it as soon as the download finishes — even if the page is not fully loaded. Use async for scripts that do not depend on the page content (like analytics). Use defer for scripts that interact with the page.

3. Console Methods

The console object has many methods beyond just log(). Here are the most useful ones:

console.log()

The workhorse. Prints any value to the console. You can pass multiple arguments separated by commas, and they will all be printed on the same line.

console.warn()

Prints a warning message with a yellow background. Use it when something is not an error but might cause problems. Browsers display a warning icon next to these messages.

console.error()

Prints an error message with a red background. Use it when something has gone wrong. Unlike console.log(), the output includes a stack trace showing where the error came from.

console.table()

Displays arrays or objects in a neat table format. This is incredibly useful when working with structured data. Pass an array of objects and the console shows a beautiful table with columns.

console.clear()

Clears all messages from the console. Useful when the console gets cluttered during debugging.

console.time() and console.timeEnd()

Measures how long a block of code takes to execute. Call console.time("label") before the code and console.timeEnd("label") after. The console will print the elapsed time in milliseconds.

4. Browser Dialog Functions

alert()

alert() shows a popup message box with an OK button. It blocks the page — the user cannot interact with anything else until they click OK. Good for learning, bad for real websites.

prompt()

prompt() shows a dialog with a text input field. It returns whatever the user types (as a string), or null if they click Cancel. You can pass a second argument as the default value.

confirm()

confirm() shows a dialog with OK and Cancel buttons. It returns true if the user clicks OK, false if they click Cancel. Useful for asking yes/no questions.

5. document.write() (And Why You Should Avoid It)

document.write() writes text directly into the HTML document. It seems convenient, but it has a dangerous behavior: if called after the page has fully loaded, it erases the entire page and replaces it with whatever you pass to it. This makes it unreliable and potentially destructive. Use .textContent or .innerHTML instead.

6. Opening the Browser DevTools

Every browser has built-in Developer Tools (DevTools). Here is how to open them:

  • Chrome/Edge: Press F12 or Ctrl + Shift + J (Windows) / Cmd + Option + J (Mac)
  • Firefox: Press F12 or Ctrl + Shift + K
  • Safari: Enable Developer menu in Preferences, then press Cmd + Option + C

The Console tab is where you will spend most of your time. You can type JavaScript directly into the console and press Enter to run it. This is perfect for testing small code snippets.

Code Examples

Inline Script vs External Script
<!-- Method 1: Inline Script -->
<!DOCTYPE html>
<html>
<body>
  <h1>Inline Script Example</h1>
  <script>
    console.log("This runs from an inline script");
  </script>
</body>
</html>

<!-- Method 2: External Script -->
<!-- index.html -->
<!DOCTYPE html>
<html>
<body>
  <h1>External Script Example</h1>
  <script src="app.js"></script>
</body>
</html>

<!-- app.js -->
console.log("This runs from an external file");
Method 1 puts JavaScript directly in the HTML. Method 2 keeps JavaScript in a separate app.js file. Both produce the same result in the console. For real projects, always use external files — it keeps your code organized and allows the browser to cache the JavaScript file separately.
Console shows: This runs from an inline script (or: This runs from an external file)
Script Placement: Head vs Body vs Defer
<!-- BAD: Script in head without defer -->
<!DOCTYPE html>
<html>
<head>
  <script>
    // This will FAIL because #greeting does not exist yet
    document.getElementById("greeting").textContent = "Hello!";
  </script>
</head>
<body>
  <p id="greeting">Waiting...</p>
</body>
</html>

<!-- GOOD: Script at end of body -->
<!DOCTYPE html>
<html>
<head></head>
<body>
  <p id="greeting">Waiting...</p>
  <script>
    document.getElementById("greeting").textContent = "Hello!";
  </script>
</body>
</html>

<!-- BEST: Script in head with defer -->
<!DOCTYPE html>
<html>
<head>
  <script src="app.js" defer></script>
</head>
<body>
  <p id="greeting">Waiting...</p>
</body>
</html>
The first example fails because the script runs before <p id="greeting"> exists. The second example works because the script runs after the element is created. The third example uses defer, which downloads the script early but waits to execute until the full page is ready. The defer approach is the modern standard.
BAD: TypeError (null reference) GOOD: Paragraph shows 'Hello!' BEST: Paragraph shows 'Hello!'
All Console Methods
// Basic logging
console.log("Regular message");
console.log("Name:", "Aarav", "Age:", 15);

// Warning (yellow background)
console.warn("This is a warning!");

// Error (red background)
console.error("Something went wrong!");

// Table (displays structured data in a table)
let students = [
  { name: "Aarav", marks: 92 },
  { name: "Priya", marks: 88 },
  { name: "Rohan", marks: 95 }
];
console.table(students);

// Timing how long code takes
console.time("loop");
for (let i = 0; i < 100000; i++) { /* empty */ }
console.timeEnd("loop");

// Clear the console
// console.clear();
console.log() accepts multiple arguments separated by commas. console.warn() and console.error() display colored messages. console.table() is excellent for viewing arrays of objects in a table format. console.time() and console.timeEnd() measure execution time. Each method serves a different purpose for debugging and development.
Regular message Name: Aarav Age: 15 (warning icon) This is a warning! (error icon) Something went wrong! (table with name and marks columns) loop: 2.345ms
alert, prompt, and confirm in Action
// alert: Show a message
alert("Welcome to Vikram's website!");

// prompt: Ask for input (returns a string or null)
let name = prompt("What is your name?", "Guest");
console.log("Hello, " + name);

// confirm: Ask yes/no (returns true or false)
let wantsCoffee = confirm("Would you like some coffee?");
if (wantsCoffee) {
  console.log("Making coffee...");
} else {
  console.log("Maybe later!");
}

// prompt always returns a STRING
let age = prompt("Enter your age:");
console.log(typeof age);  // "string" even if user types a number!
These three functions create browser popup dialogs. alert() just shows a message. prompt() returns the typed text as a string (the second argument "Guest" is the default value). confirm() returns true for OK, false for Cancel. Critical detail: prompt() always returns a string, even if the user types a number like 42 — you get "42" and need to convert it with Number().
If user enters 'Priya' for name and clicks OK for coffee: Hello, Priya Making coffee... string
Why document.write() Is Dangerous
<!-- This seems to work when the page loads -->
<!DOCTYPE html>
<html>
<body>
  <h1>My Page</h1>
  <script>
    document.write("<p>Added by JavaScript</p>");
  </script>
  <p>This paragraph stays.</p>
</body>
</html>

<!-- BUT THIS DESTROYS THE PAGE: -->
<!DOCTYPE html>
<html>
<body>
  <h1>My Page</h1>
  <p>Important content here</p>
  <button onclick="document.write('Oops!')">Click Me</button>
</body>
</html>
When document.write() runs during page loading (as the browser reads the HTML), it inserts content into the page. But when called after the page has loaded (like from a button click), it erases the entire page and replaces everything with the new content. In the second example, clicking the button wipes out the heading, paragraph, and button — replacing it all with just "Oops!". This is why document.write() should be avoided.
First example: Page shows heading, 'Added by JavaScript', and paragraph. Second example: Clicking the button erases everything and shows only 'Oops!'
Multiple Script Tags and Execution Order
<!DOCTYPE html>
<html>
<body>
  <script>
    console.log("Script 1 runs first");
    let message = "Hello";
  </script>

  <p>Some HTML content here</p>

  <script>
    console.log("Script 2 runs second");
    console.log(message);  // Can access variable from Script 1
    message = message + " World";
  </script>

  <script>
    console.log("Script 3 runs third");
    console.log(message);  // "Hello World"
  </script>
</body>
</html>
Multiple script tags on a page execute in order, from top to bottom. They share the same global scope, so a variable declared in Script 1 is accessible in Script 2 and Script 3. This is important to understand: all scripts on a page share the same variable space unless you use modules.
Script 1 runs first Script 2 runs second Hello Script 3 runs third Hello World
Using the Console as a Calculator and Scratchpad
// You can type these directly into the browser console (F12)

// Math
25 * 4          // 100
Math.sqrt(144)  // 12
Math.PI         // 3.141592653589793

// String operations
"Ananya".length         // 6
"Ananya".toUpperCase()  // "ANANYA"
"Hello World".split(" ") // ["Hello", "World"]

// Quick tests
typeof 42        // "number"
typeof null      // "object"
5 > 3            // true
"5" === 5        // false

// Even create elements on the fly
document.title = "I changed the tab title!";
The browser console is a live JavaScript environment. You can type any expression and immediately see the result. Use it as a calculator, test string methods, check types, or even modify the current page. This is the fastest way to experiment with JavaScript. Every professional developer uses the console daily.
Each expression returns its result immediately in the console.

Common Mistakes

Mixing src Attribute with Inline Code

<script src="app.js">
  console.log("This will be ignored!");
</script>
No error, but the inline code never runs. Only app.js executes.
<script src="app.js"></script>
<script>
  console.log("This runs from a separate inline script");
</script>
When a <script> tag has a src attribute, the browser ignores any code between the opening and closing tags. If you need both an external file and inline code, use two separate <script> tags.

Forgetting the Closing Script Tag

<script src="app.js" />
<p>This paragraph might not show up</p>
The paragraph and everything after may be treated as part of the script and hidden.
<script src="app.js"></script>
<p>This paragraph shows up correctly</p>
Unlike some HTML tags (like <img />), the <script> tag is not self-closing. You must always write the full closing tag </script>. Using a self-closing <script /> can cause the browser to treat all subsequent HTML as script content.

Using console.log to Display on the Page

// Neha wants to show a message on the page
console.log("Welcome to my website!");
// But nothing appears on the page!
No error, but the message only appears in the DevTools console, not on the web page.
// To display text ON the page, use DOM methods:
document.getElementById("output").textContent = "Welcome to my website!";

// Or for quick testing, alert works:
alert("Welcome to my website!");
console.log() prints to the browser's Developer Console (F12), not to the visible web page. To display something on the page, you need to modify an HTML element using .textContent, .innerHTML, or .innerText. This is one of the most common beginner confusions.

Using prompt Without Converting the Type

let a = prompt("Enter first number:");   // returns "5"
let b = prompt("Enter second number:");   // returns "3"
let sum = a + b;
console.log("Sum: " + sum);  // Shows "Sum: 53" instead of "Sum: 8"
No error, but the result is '53' (string concatenation) instead of 8 (addition).
let a = Number(prompt("Enter first number:"));
let b = Number(prompt("Enter second number:"));
let sum = a + b;
console.log("Sum: " + sum);  // Shows "Sum: 8"
prompt() always returns a string, even when the user types a number. "5" + "3" is string concatenation, giving "53". Wrap the prompt in Number() to convert the string to a number first: Number("5") + Number("3") = 8.

Calling document.write After Page Load

<!DOCTYPE html>
<html>
<body>
  <h1>My Important Page</h1>
  <button onclick="document.write('Hello!')">Click</button>
</body>
</html>
Clicking the button erases the entire page (heading and button disappear) and shows only 'Hello!'.
<!DOCTYPE html>
<html>
<body>
  <h1>My Important Page</h1>
  <p id="output"></p>
  <button onclick="document.getElementById('output').textContent = 'Hello!'">Click</button>
</body>
</html>
When document.write() is called after the page has finished loading (e.g., from a button click), it destroys the entire page content and replaces it. Use .textContent or .innerHTML to update specific elements instead.

Summary

  • JavaScript is added to HTML using the <script> tag. You can write code inline between the tags or link an external .js file using the src attribute.
  • When a script tag has a src attribute, any code between the opening and closing tags is ignored. Use separate script tags for external and inline code.
  • Script placement matters: scripts in the <head> run before the page is built (can cause errors). Scripts before </body> run after all elements exist.
  • The defer attribute lets you place scripts in the <head> while ensuring they run only after the full page is loaded. This is the modern best practice.
  • console.log() prints output to the browser's Developer Console (F12), not to the web page. Use it constantly for testing and debugging.
  • console.warn() shows yellow warnings, console.error() shows red errors, and console.table() displays data in a table format.
  • alert() shows a popup message. prompt() asks for text input and returns a string (or null). confirm() asks yes/no and returns true or false.
  • prompt() always returns a string. Use Number() to convert it when you need a number for calculations.
  • document.write() writes to the page during load, but erases everything if called after the page has loaded. Avoid it. Use textContent or innerHTML instead.
  • The browser console (F12) is a live JavaScript environment. You can type code, test expressions, and debug errors directly in it.

Ready to Practice?

Test your understanding with 50+ practice questions on this topic.

Go to Practice Questions

Want to learn web development with a live mentor?

Explore our Frontend Masterclass