Contact, if you are interested in this website / domain name / Sponsorship / Advertisement / Partnership
HomeLearnToolsRoadmapVideosBuildSponsorshipAboutContactStart a project
Beginner

JavaScript Fundamentals Explained Simply

12 minute read · Last updated 2026-10-31 · Written and reviewed by the Code.House editorial team

JavaScript has accumulated a lot of syntax over thirty years, but day-to-day work uses a narrow slice of it. This guide covers that slice: how values are declared, how functions behave, how to work with arrays, and how asynchronous code actually runs.

Declaring values

Use const by default and let when a value is reassigned. There is no modern reason to write var: it ignores block scope, which produces bugs that are hard to see.

const rate = 0.08;        // cannot be reassigned
let total = 0;            // will change
total = 100 * (1 + rate);

const prevents reassignment, not mutation. An array declared with const can still have items pushed into it — what cannot change is which array the name points at.

Functions and arrow functions

function area(width, height) {
  return width * height;
}

const areaArrow = (width, height) => width * height;

Arrow functions are shorter and, importantly, do not create their own this. That is why they are the right choice inside callbacks and class methods that pass functions around. A traditional function declaration is hoisted, meaning you can call it before the line where it is defined; arrow functions assigned to a const are not.

Default parameters and rest arguments remove a lot of defensive code:

function invoice(amount, currency = 'CAD', ...notes) {
  return `${amount} ${currency} ${notes.join('; ')}`;
}

Working with arrays

Four methods cover most data work. They all return a new array or value rather than modifying the original, which makes them safe to chain.

const orders = [
  { id: 1, total: 120, paid: true },
  { id: 2, total: 80,  paid: false },
  { id: 3, total: 200, paid: true },
];

orders.filter(o => o.paid);                    // keep matching items
orders.map(o => o.total);                      // transform each item
orders.reduce((sum, o) => sum + o.total, 0);   // collapse to one value
orders.find(o => o.id === 2);                  // first match, or undefined

Destructuring and spread keep object work readable:

const { id, total } = orders[0];
const updated = { ...orders[0], paid: false };   // copy with one change

Asynchronous code

JavaScript runs on a single thread. Anything slow — a network request, a file read, a timer — is handed off and its result arrives later. A promise represents that future result.

async function loadUser(id) {
  const response = await fetch(`/api/users/${id}`);
  if (!response.ok) {
    throw new Error(`Request failed: ${response.status}`);
  }
  return response.json();
}

try {
  const user = await loadUser(42);
  console.log(user.name);
} catch (error) {
  console.error('Could not load the user:', error.message);
}

Two details catch people out. First, fetch only rejects on network failure — a 404 or a 500 still resolves, so you must check response.ok yourself. Second, await inside a loop runs requests one after another. When the requests are independent, start them together:

const users = await Promise.all(ids.map(loadUser));

Touching the page

const button = document.querySelector('#save');

button.addEventListener('click', (event) => {
  event.preventDefault();
  document.querySelector('#status').textContent = 'Saved';
});

Prefer textContent over innerHTML whenever you insert text. innerHTML parses whatever you give it as markup, so any value that came from a user or an API can inject script. If you must build markup, escape the values first.

Reading and writing the DOM is comparatively slow. In a loop, build a string or a document fragment and insert once, rather than appending inside each iteration.

Mistakes worth avoiding early

  • Comparing with ==. Use ===, which does not coerce types, and avoid the surprise that '' == 0 is true.
  • Forgetting that typeof null returns 'object'. Check for null explicitly.
  • Mutating an array while looping over it. Build a new one instead.
  • Leaving console.log in production code that handles personal data.
  • Storing anything sensitive in localStorage. It is readable by any script on the page.

Common questions

Should I learn TypeScript next?

Once you are comfortable with functions, objects and async code, yes. TypeScript is JavaScript plus a type checker, and most of the learning curve is the type system rather than new runtime behaviour.

Do I need a framework to build something real?

No. Plain JavaScript handles forms, fetch calls and interactive widgets well. Frameworks earn their keep when an application has a lot of shared, changing state across many views.

Keep reading

Spotted something out of date? Send a correction — guides are revised rather than quietly deleted.