Chapter 06 — Front-End Fundamentals

Vanilla JavaScript

HTML gives a page structure. CSS gives it style. JavaScript gives it behavior.

“Vanilla JS” means plain JavaScript with no frameworks or libraries: just the language itself and what the browser exposes. Frameworks like React are built on top of vanilla JS. Understanding what’s underneath makes you better at using the frameworks, and gives you the ability to solve problems without reaching for one.


Add a script file

In VS Code, right-click the src folder and create a new file: main.js. Or from the integrated terminal:

bash~/tutorials/
touch src/main.js

Link it to your HTML. Add this line at the bottom of index.html, just before the closing </body> tag:

html~/tutorials/
  <script src="main.js"></script>
</body>

Placing the script at the bottom means the browser parses your HTML and builds the page before it runs your JavaScript. This matters because JavaScript often needs to find and manipulate HTML elements, and those elements need to exist first.


The browser console

Before writing any code, open the browser’s developer tools. In Chrome or Firefox on macOS press Cmd+Option+J. On Ubuntu press Ctrl+Shift+J. This opens the console, where JavaScript output appears and errors are reported.

Run this in your main.js:

js~/tutorials/
console.log('Script loaded');

Save the file. If Live Preview is running, look at the console in developer tools. You should see Script loaded. If you don’t, check that the <script> tag in your HTML points to the right file path.

The console is your primary debugging tool. You’ll use it constantly.


Variables

JavaScript has two ways to declare variables: const and let.

js~/tutorials/
const siteName = 'My Project';
let pageCount = 1;

Use const when the value won’t change. Use let when it will. You’ll see var in older code and tutorials, but it has scoping behavior that causes subtle bugs. Don’t use it in new code.

js~/tutorials/
const siteName = 'My Project';
siteName = 'Something else'; // Error: Assignment to constant variable

let pageCount = 1;
pageCount = 2; // Fine

Data types

JavaScript has a handful of primitive types you’ll use all the time:

js~/tutorials/
const title = 'Getting started'; // string
const count = 15;                // number
const isPublished = true;        // boolean
const nothing = null;            // null, intentionally empty
let draft;                       // undefined, declared but not assigned

And two complex types:

js~/tutorials/
// Array: an ordered list of values
const chapters = ['Terminal', 'Git', 'HTML', 'CSS', 'JavaScript'];

// Object: a collection of key-value pairs
const project = {
  name: 'Tutorials',
  author: 'Your Name',
  chapterCount: 17,
};

Arrays and objects are how you’ll represent most data in real applications.


Functions

A function is a reusable block of code.

js~/tutorials/
function greet(name) {
  return 'Hello, ' + name;
}

console.log(greet('Justin')); // Hello, Justin

You’ll also see functions written as arrow functions, which are common in modern JavaScript:

js~/tutorials/
const greet = (name) => {
  return 'Hello, ' + name;
};

For single-expression arrow functions, the return is implicit:

js~/tutorials/
const greet = (name) => 'Hello, ' + name;

All three do the same thing. Arrow functions come up constantly in the chapters on modular JS and React. Getting comfortable with them now pays off later.


The DOM

The DOM, Document Object Model, is the browser’s representation of your HTML as a tree of objects that JavaScript can read and modify. When you use JavaScript to change what appears on a page, you’re manipulating the DOM.

document.querySelector() finds the first element on the page that matches a CSS selector:

js~/tutorials/
const heading = document.querySelector('h1');
console.log(heading.textContent); // Logs the text inside your h1

document.querySelectorAll() finds all matching elements and returns a NodeList:

js~/tutorials/
const allLinks = document.querySelectorAll('nav a');
console.log(allLinks.length); // Number of links in your nav

Once you have an element, you can read or change its content, attributes, and styles:

js~/tutorials/
const heading = document.querySelector('h1');
heading.textContent = 'Updated heading text';
heading.style.color = 'red';

That last line, setting styles directly in JavaScript, is something to do sparingly. Prefer adding and removing CSS classes instead. Keeps the style logic in CSS where it belongs:

js~/tutorials/
heading.classList.add('is-active');
heading.classList.remove('is-active');
heading.classList.toggle('is-active');

Events

Events are things that happen in the browser: a click, a keypress, a form submission, the page finishing loading. JavaScript listens for events and responds to them with addEventListener.

Add a button to your index.html, inside <main>:

html~/tutorials/
<button id="toggle-btn" type="button">Toggle intro</button>

Now handle a click on it in main.js:

js~/tutorials/
const btn = document.querySelector('#toggle-btn');
const intro = document.querySelector('.intro');

btn.addEventListener('click', () => {
  intro.classList.toggle('is-hidden');
});

Add the class to style.css:

css~/tutorials/
.is-hidden {
  display: none;
}

Save everything. Click the button. The paragraph appears and disappears. That’s event-driven DOM manipulation: the fundamental pattern behind almost every interactive thing on the web.


A note on type="button"

The <button> element defaults to type="submit" inside a form. Outside a form it does nothing, but setting type="button" explicitly makes intent clear and prevents unexpected behavior if the button ends up inside a form later. It’s a small habit worth building.


Commit your work

bash~/tutorials/
git add .
git commit -m "Add JavaScript for toggle interaction"

What you now know

You can declare variables, write functions, find elements in the DOM, and respond to user events. That’s the foundation. In Chapter 7 you’ll install Node and npm, which open up the JavaScript tooling ecosystem and make the next several chapters possible.

Reference