JSTAcademy
0 XP
Dashboard
Crash Courses
Environment, Types & Your First Real Function
12 min
Basic+150 XP
Crash Courses · Basic

Environment, Types & Your First Real Function

Set up VS Code for JavaScript, understand types from first principles, and write your first multi-file program.
12 min read+150 XP on completionCert: JavaScript Crash Course
Tap any word in the text below to start reading from there.

Environment, Types & Your First Real Function

Why JavaScript First?

JavaScript is the only language that runs natively in every browser — no install, no compile step. It also runs server-side via Node.js. React, Next.js, TypeScript — they all compile down to JavaScript. Mastering fundamentals removes the magic from every framework above them.

Before you write a single line: your environment must be correct.

---

Setting Up VS Code for JavaScript

Open VS Code. Install these extensions once — they will make every lesson easier:

  1. ESLint — catches errors before you run code
  2. Prettier — auto-formats on save
  3. JavaScript (ES2022+) snippets — built into VS Code already

Create your project folder (Terminal > New Terminal in VS Code):

mkdir js-crash-course
cd js-crash-course
code .

Enable auto-format on save — open Settings (Ctrl+,), search "format on save", check the box.

---

Running JavaScript: Two Environments

In the browser — open DevTools (F12), Console tab. Type JS directly. Use this for DOM work.

In Node.js — run any .js file from terminal:

node main.js

You'll use Node.js for everything in this crash course.

---

Variables: Three Keywords, One Rule

const name = 'Jordan'      // cannot be reassigned — use this 90% of the time
let count = 0              // reassignable — use only when value changes
var old = 'avoid'          // function-scoped, hoisted — legacy code only

The rule: default to `const`. Use `let` when the value must change. Never `var`.

Why does this matter? var is hoisted to the top of its function, which causes subtle bugs:

// var leaks out of if blocks
if (true) {
  var x = 10
}
console.log(x)  // 10 — var escapes the block

// const stays in its block
if (true) {
  const y = 10
}
console.log(y)  // ReferenceError — y doesn't exist here

---

The 8 Data Types

typeof 'hello'           // 'string'
typeof 42                // 'number'  (covers integers and floats — JS has no int)
typeof 9007199254740991n // 'bigint'  (for numbers larger than Number.MAX_SAFE_INTEGER)
typeof true              // 'boolean'
typeof undefined         // 'undefined'  (default of unassigned variables)
typeof null              // 'object'  ← a 25-year-old JS bug, never fixed
typeof Symbol()          // 'symbol'  (unique identifiers, used in advanced JS)
typeof {}                // 'object'  (arrays are also objects)

Primitives are immutable and passed by value. Objects are passed by reference.

let a = 'hello'
let b = a
b = 'world'
console.log(a)  // 'hello' — primitives copied

const obj1 = { x: 1 }
const obj2 = obj1
obj2.x = 99
console.log(obj1.x)  // 99 — objects share reference

---

Functions: Three Forms

// 1. Function declaration — hoisted, callable before its definition
function greet(name) {
  return `Hello, ${name}`
}

// 2. Arrow function — concise, no own this binding
const greet = (name) => `Hello, ${name}`

// 3. Function expression — not hoisted
const greet = function(name) { return `Hello, ${name}` }

Use arrow functions for callbacks and short functions. Use declarations for top-level named functions.

---

Your First Multi-File Program

Real projects split code across files. Here's how it works:

utils.js — utility functions exported for other files to use:

// utils.js
export function formatCurrency(amount, currency = 'USD') {
  return new Intl.NumberFormat('en-US', {
    style: 'currency',
    currency,
  }).format(amount)
}

export function capitalize(str) {
  return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase()
}

main.js — the entry point that imports and uses utils.js:

// main.js
import { formatCurrency, capitalize } from './utils.js'

const products = [
  { name: 'laptop', price: 1299 },
  { name: 'keyboard', price: 89 },
]

products.forEach(p => {
  console.log(`${capitalize(p.name)}: ${formatCurrency(p.price)}`)
})

Run it:

node --input-type=module < main.js
# Or add "type": "module" to package.json and run: node main.js

The export keyword makes a function available. The import keyword pulls it in. Files connect through explicit imports — nothing is global by default in modern JS.

---

Closures: How State Lives Inside Functions

This is the most important pattern in JavaScript — React's useState is built on it:

function makeCounter(start = 0) {
  let count = start  // this variable lives INSIDE makeCounter's scope
  return {
    inc: () => ++count,   // this arrow function closes over count
    dec: () => --count,
    get: () => count,
  }
}

const counter = makeCounter(10)
counter.inc()  // 11
counter.inc()  // 12
counter.dec()  // 11
console.log(counter.get())  // 11

count outlives makeCounter's execution because the returned functions hold a reference to it. That's a closure.

---

Truthiness & Safe Access

Falsy values: false, 0, '', null, undefined, NaN. Everything else is truthy.

const user = null
const name = user?.name ?? 'Guest'   // optional chaining + nullish coalescing
// user?.name = undefined (safe, doesn't throw)
// ?? 'Guest'  = use right side only when left is null/undefined
0%