Running JavaScript: the console, script tags and Node.js

Run code in the browser console, load scripts into a page with the script element and defer, and run files with Node.js.

  • Beginner
  • 8 min read
  • Updated 17 Oct 2026

What you will learn

  • Run code in the console
  • Load a script file correctly
  • Run a JavaScript file with Node.js
  • Explain why defer and type="module" scripts can safely use the page's elements

Before you start

Before you can learn a language, you need somewhere to type it. This lesson shows three places to run JavaScript: the browser console for quick experiments, a script element for real pages, and Node.js for running files outside the browser.

The browser console

Every modern browser has developer tools, and every set of developer tools has a console. It runs any JavaScript you type and shows the result straight away.

Open it with:

  • Windows and Linux: Ctrl + Shift + J in Chrome and Edge, Ctrl + Shift + K in Firefox
  • macOS: Cmd + Option + J in Chrome and Edge, Cmd + Option + K in Firefox
  • Safari: first turn on the developer menu in Settings, under Advanced, then press Cmd + Option + C

Type this and press Enter:

JavaScript
2 + 3
// → 5

The console evaluates the expression and prints the result. Now try printing a message with console.log:

JavaScript
console.log("Hello from the console");
// Hello from the console
// → undefined

The first line is the message. The undefined afterwards is the console reporting what the console.log call itself returned, which is nothing. You can ignore it.

A few tips make the console more pleasant:

  • Press the up arrow to bring back previous commands.
  • Press Shift + Enter to start a new line without running the code, so you can type several lines.
  • The console runs code against the current page, so document.title shows the title of whatever page is open.

In this course, comments starting with // → show the value an example produces. Lines printed by console.log are shown as plain comments.

The console is perfect for trying things, but anything you type is lost when you reload. Real code lives in files.

Adding JavaScript to a page

The HTML script element loads JavaScript into a page. You can write code directly inside it, but you should almost always put it in a separate file and link to it with src.

Create a folder with two files. First, index.html:

HTML
<!doctype html>
<html lang="en-GB">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>My first script</title>
  <script src="app.js" defer></script>
</head>
<body>
  <h1>My first script</h1>
  <p id="message">This text will change.</p>
</body>
</html>

Then app.js, in the same folder:

JavaScript
console.log("app.js has loaded");

const message = document.querySelector("#message");
message.textContent = "JavaScript changed this text.";

Open index.html in your browser. The paragraph shows the new text, and the console shows the log message. A separate file can be cached by the browser, reused across pages, and edited with proper syntax highlighting, which is why it beats inline code.

Notice that the script element is written with an opening and closing tag even though it has no content. script is not a void element, so <script src="app.js" /> does not work.

Why defer matters

By default, when the browser's HTML parser meets a script element, it stops building the page, downloads the script, runs it, and only then carries on. That causes two problems:

  1. Slower pages. Nothing below the script appears until the script has downloaded and run.
  2. Missing elements. A script in the head runs before the body exists, so document.querySelector("#message") finds nothing and returns null.

Remove defer from the example above and reload. The console shows an error like this:

Plain text
Uncaught TypeError: Cannot set properties of null (setting 'textContent')

The paragraph did not exist yet when the script ran.

The defer attribute fixes both problems. A deferred script downloads in parallel while the page is parsed, then runs once parsing has finished, just before the DOMContentLoaded event. Several deferred scripts run in the order they appear in the HTML. It is the right default for almost every script.

ScriptBlocks parsing?When it runsOrder kept?
<script src>YesAs soon as downloadedYes
<script src defer>NoAfter the document is parsedYes
<script src async>NoAs soon as downloadedNo
<script type="module" src>NoAfter the document is parsed, like deferYes

async scripts run whenever they finish downloading, possibly before the page is parsed and in any order. They suit independent scripts such as analytics, not code that works with your page. The HTML Complete Course covers script loading and performance in more depth.

You will also see older code that puts <script src="app.js"></script> at the very end of the body to get the same effect. It works, but defer in the head lets the download start earlier.

Module scripts

Later in the course you will split code into modules with import and export. Modules are loaded with type="module":

HTML
<script type="module" src="app.js"></script>

Module scripts are deferred automatically, so you do not add defer. They also run in strict mode, which turns some silent mistakes into errors. One catch: module scripts do not load from pages opened directly from your disk with a file:// address, so for module examples you will run a small local server, such as the VS Code Live Server extension or npx serve. The modules lesson covers this.

Running JavaScript with Node.js

Node.js runs JavaScript files outside the browser. Download the LTS (long-term support) version from nodejs.org and install it. Then open a terminal and check it works:

Shell
node --version

You should see a version number such as v20.11.0 or later.

Create a file called hello.js:

JavaScript
const name = "Node.js";
console.log(`Hello from ${name}`);
console.log(2 + 3);

Run it from the folder that contains it:

Shell
node hello.js
Plain text
Hello from Node.js
5

console.log prints to the terminal instead of a browser console. Most examples in this course that do not touch the page run unchanged in Node.js. Examples that use document or buttons only work in a browser, because Node.js has no page.

You can also type node on its own to open an interactive prompt, called the REPL, which behaves much like the browser console. Press Ctrl + C twice to leave it.

Node.js treats .js files as older CommonJS scripts unless the nearest package.json contains "type": "module", or the file ends in .mjs. That only matters once you use import and export, and lesson 34 covers it.

Reading your first error

Mistakes are normal, and the console tells you about them. Try this in the console:

JavaScript
consol.log("oops");
// Uncaught ReferenceError: consol is not defined

The message has three useful parts:

  • The type, ReferenceError, which tells you the kind of problem. Here, a name that does not exist.
  • The description, which says which name it was.
  • The location. In a file, the console shows the file name and line number. Click it to jump to the code.

Read the whole message before changing anything. Most early errors are typing mistakes that the message points straight at. Lesson 18 covers debugging in depth.

Comments

You will see comments in every example. JavaScript ignores them:

JavaScript
// A single-line comment runs to the end of the line.

/*
  A multi-line comment
  can span several lines.
*/

Use comments to explain why code does something, not to repeat what it obviously does.

Summary

  • The browser console runs JavaScript immediately and is ideal for experiments.
  • Put page scripts in separate files and load them with <script src="..." defer></script> in the head.
  • defer stops the script blocking the page and runs it after the HTML is parsed, so your elements exist.
  • type="module" scripts are deferred automatically.
  • node file.js runs a file with Node.js; browser-only APIs such as document do not exist there.
  • Error messages give a type, a description and a location. Read them before changing code.

Further reading