---
title: 'Ways to Run Code'
source: 'https://academia.sh/en/courses/javascript-fundamentals/ways-to-run-code'
course: 'JavaScript Fundamentals'
language: en
updated: '2026-08-23T07:00:58+00:00'
license: 'CC BY-SA 4.0'
---

# Ways to Run Code

Running from a file, the interactive shell, the browser console, and the script tag; the script–module distinction and reading an error message.

The previous lesson showed that which names a script can see depends on the host
environment. This lesson looks at how code is handed to those environments: a file from
the command line, an interactive shell session, the browser console, and a script tag
attached to a page. The four paths are not merely "ways to start code"; each also
determines the rules under which the code will be interpreted.

The same measurement script will be run through all of these paths. Where the results
match and where they diverge draws the boundary between the language's core and the
environment's contribution a second time.

## Running a File from the Command Line

The server-side runtime takes its source from a file. The examples in this course have
been run with the `node` command; the name and extension given to the file determine how
the source is interpreted.

A file named `measurement.mjs`:

```js
const temperatures = [21.5, 19.75, 23, 18.25];
let total = 0;
for (const value of temperatures) {
  total += value;
}
console.log("reading count:", temperatures.length);
console.log("average:", total / temperatures.length);
```

```sh
node measurement.mjs
```

```
reading count: 4
average: 20.625
```

The file is read start to finish, parsed, and executed. The process ends once no
pending work is left after the code's last line finishes.

For one-line experiments, there is no need to open a file; the source can be given
directly as an argument:

```sh
node -e 'console.log(Math.max(21.5, 19.75, 23))'
```

```
23
```

## The Interactive Shell

When called with no arguments, the runtime opens an **interactive shell (REPL)**. This
shell reads each line, evaluates it, prints the result, and loops back. Its name comes
from these four steps.

```
> const temperatures = [21.5, 19.75, 23, 18.25];
undefined
> temperatures.length
4
> Math.max(...temperatures)
23
> typeof temperatures
'object'
```

Two observations are enough to understand this shell.

First: the shell prints each line's **value**. A declaration statement produces no
value; this is why the first line's result is `undefined`. This does not mean the
declaration failed — the next line reads the variable without any problem. The
statement–expression distinction from the Programming Fundamentals course becomes
directly visible here: `const` is a statement, `temperatures.length` is an expression.

Second: the format the shell prints is not the same as the `console.log` format. The
result of `typeof` was written in the shell as `'object'`, with quotes; printed with
`console.log`, the same value would appear as `object`, without quotes. The shell prints
a value in an **inspection format**: strings are quoted, so the number `4` and the text
`'4'` can be told apart. This format's details are specific to the runtime and are not
defined in the standard.

The same difference shows up with objects too:

```js
const record = { station: "A1", temperature: 21.5 };
console.log(record);
console.log(String(record));
```

```
{ station: 'A1', temperature: 21.5 }
[object Object]
```

The readable form on the first line is the environment's inspection format. The second
line is the result of the language's own to-string rule and is the same in every
environment. The browser console shows a collapsible tree for the first line; the
second line still produces `[object Object]` there too.

## The Browser Console and the Script Tag

In a document-based environment, code enters two ways. The **console** is an
interactive shell opened in the context of the page; the same rules above apply exactly.
The **script tag** binds code to the page's loading process:

```html
<script src="measurement.js"></script>
```

The tag's position and attributes determine the moment of execution. If no attribute is
given, document parsing stops, the source is downloaded and run, then parsing resumes.
The `defer` attribute delays execution to the end of document parsing; the
`type="module"` attribute both applies the same delay and loads the source as a module
rather than a script.

This course's examples can be verified in the console and from the command line; since
they do not touch document objects, they do not require a page context. Code that
accesses the document is the subject of the host environment, not the language.

## Script or Module

ECMAScript parses a source text according to one of two separate targets: **script**
and **module**. This is a decision derived from the file extension or the tag's
attribute, and it produces three concrete differences.

The first difference is **strict mode**. Source loaded as a module always runs in
strict mode; source loaded as a script does not, unless requested separately. Strict
mode turns several behaviors that would silently produce a wrong result into an error.
Its most visible example is assigning to an undeclared name:

```js
try {
  undeclaredName = 5;
} catch (error) {
  console.log(error.name + ": " + error.message);
}
```

When run as a module (with an `.mjs` extension):

```
ReferenceError: undeclaredName is not defined
```

The same assignment throws no error in a non-strict script; it silently creates a global
name. This is why a name created by a typo can go on living throughout the program.

The second difference is **the value of `this` in the outermost scope**. In a module,
this value is `undefined`; in a script, it is an object chosen by the environment.

The third difference is **whether names declared in the outermost scope get written
onto the global object**. In a module, the outermost scope is private to the module;
no name declared there becomes a property of the global object:

```js
var x = 1;
console.log(typeof this);
console.log(typeof globalThis.x);
```

When run as a module:

```
undefined
undefined
```

In a source loaded as a classic script, on the other hand, outermost-scope names
declared with `var` do become properties of the global object. Two files accidentally
overwriting each other's names is a consequence of this behavior; the module model
removes this sharing.

Throughout this course, examples have been run as modules. If an example behaves
differently only in script mode, this will be noted separately in the text.

## Reading an Error Message

An uncaught error carries three pieces of information: the error's **name**,
**message**, and **stack trace**. All three can be read separately:

```js
const records = [{ station: "A1", temperature: 21.5 }];
try {
  console.log(records[1].temperature);
} catch (error) {
  console.log("name   :", error.name);
  console.log("message:", error.message);
}
```

```
name   : TypeError
message: Cannot read properties of undefined (reading 'temperature')
```

**Name** gives the error's class. `TypeError` reports that a value was not of the
expected kind, `ReferenceError` that a name could not be found, `SyntaxError` that the
source could not be parsed.

**Message** is the event's detail. Reading the message above step by step directly says
where the error is: the value of `records[1]` came out `undefined`, and a `temperature`
property was then looked up on `undefined`. So the real problem is that the array's
second element does not exist — not the property's name. An error message shows the
**symptom** of the error; the cause is usually a line above it.

**Stack trace** lists, in lines starting with `at`, the call chain the error passed
through: the topmost line is where it occurred, the lines below give who called from
where. Because its format, file paths, and the runtime's internal frames vary by
machine, only the name and message sections will be shown in this course.

An uncaught error terminates the process with a nonzero exit code in a server-side
runtime. In a browser, the page keeps running; the error is only written to the
console. The same error's outcome differs across the two environments, but its message
is the same.

## Summary

- Code enters four ways: a file, a command-line argument, an interactive shell, and a
  script tag in a document context.
- The interactive shell prints each line's value in an inspection format; because
  declarations produce no value, `undefined` appears. This format comes from the
  environment, not the standard.
- ECMAScript parses a source as either a script or a module; a module always runs in
  strict mode, its outermost `this` value is `undefined`, and its names are not written
  onto the global object.
- Strict mode turns assignment to an undeclared name into a `ReferenceError` instead of
  silently creating a global name.
- An error message is made up of name, message, and stack trace; the message describes
  the symptom, and the cause is usually in the step before it.

## Next Step

The script being loaded as a module, the presence of `const` and `let` declarations,
the `for...of` loop — all of these are abilities the language gained at a specific
point. The next lesson takes up how a feature enters the language: how the standard is
versioned, the stages a proposal passes through, and how the question "does this
feature exist here" gets answered without looking at a version name.
