A practical beginner guide to JavaScript syntax, variables, conditions, functions, arrays, objects, the DOM, events, and a complete counter project.
Prefer following along visually? Start with the complete video, then use the written guide as a reference whenever you need it.
JavaScript is what makes a website feel alive. It can respond to clicks, update content, perform calculations, validate information, and change what appears on a page without reloading it.
In this guide, we're going to learn the core JavaScript concepts in a practical order. We'll start with a simple browser project, add one concept at a time, and then combine variables, functions, conditions, DOM selection, and events in a working counter.
You don't need any previous JavaScript experience. Basic HTML is helpful, but I'll explain every JavaScript concept from the beginning and keep the examples small enough to understand.
HTML gives us the structure of a page, and CSS controls how it looks. JavaScript adds the behavior. It can listen for an action, make a decision, update a value, and change the page right in front of us.
The browser runs JavaScript and provides tools such as the console and the Document Object Model, commonly called the DOM. The console helps us inspect values and errors. The DOM gives JavaScript access to HTML elements.
All right, first let's create a folder named my-first-js-project and open it in Visual Studio Code. Inside it, we only need two files:
index.html contains the webpage.script.js contains the JavaScript.Now let's connect the JavaScript file inside the HTML head:
<script src="script.js" defer></script>
The src attribute tells the browser which file to load. The defer attribute lets the browser finish reading the HTML before it runs the JavaScript.
After that, open index.html with Live Server. In the browser, open Developer Tools and select the Console panel. Now we can change the code, save it, and immediately inspect the result.
Now let's run our first JavaScript statement. The console.log() method displays a value in the browser console:
console.log("Hello, JavaScript!");
The text inside quotation marks is a string. Parentheses contain the value passed to console.log(), and the semicolon marks the end of the statement.
JavaScript comments leave notes in the code without running them:
// This is a single-line comment.
/* This comment
can use multiple lines. */
Next, let's store some values so we can reuse them. Use const when the variable should keep the same assignment, and use let when that assignment needs to change.
const userName = "Sahand";
let score = 0;
score = 1;
For me, const is the best default. I only reach for let when I know the value needs to change. You'll still see var in older code, but you don't need it for the examples in this guide.
Use descriptive camelCase names such as userName, totalPrice, and isLoggedIn rather than unclear names such as x or data1.
| const default | let flexible |
|---|---|
| Default choice | Use when the value must change |
| No reassignment | Allows reassignment |
| Clear intention | Changing state |
So far, we've stored text and numbers. JavaScript values can represent several different kinds of information:
const courseName = "JavaScript Basics"; // string
const lessonCount = 14; // number
const isBeginner = true; // boolean
let nextLesson; // undefined
const selectedProject = null; // intentionally empty
The typeof operator reports the type of most values:
console.log(typeof courseName); // "string"
console.log(typeof lessonCount); // "number"
console.log(typeof isBeginner); // "boolean"
Just a warning: typeof null returns "object". This is a historical JavaScript quirk. For now, think of null as an intentionally empty value.
Arithmetic operators perform calculations:
console.log(10 + 5);
console.log(10 - 5);
console.log(10 * 5);
console.log(10 / 5);
Comparison operators produce boolean values. Use strict equality, ===, as the beginner default because it compares both value and type without automatic type conversion.
console.log(10 > 5); // true
console.log(10 === 10); // true
console.log(10 === "10"); // false
Logical operators combine or reverse conditions:
&& requires both conditions to be true.|| requires at least one condition to be true.! reverses a boolean result.Now let's make the code choose what to do. An if statement runs only when its condition is true. We can add else if for another test and else for everything remaining.
const age = 15;
if (age < 13) {
console.log("You are a child.");
} else if (age < 18) {
console.log("You are a teenager.");
} else {
console.log("You are an adult.");
}
JavaScript checks these conditions from top to bottom and stops after the first true one. Put specific cases before broader cases so the intended branch can run.
JavaScript stops after the first matching condition.
if conditionif blockelse if conditionelse blockif conditionNext, let's stop repeating logic. A function groups code under one name so we can run it whenever we need it. Parameters are placeholders, arguments are the real values we provide, and return sends the result back.
function greet(name) {
return `Hello, ${name}!`;
}
const message = greet("Sahand");
console.log(message);
The same function can receive different arguments without duplicating its logic. JavaScript also supports arrow functions:
const add = (numberOne, numberTwo) => {
return numberOne + numberTwo;
};
Regular functions are often easier to recognize at first. Arrow functions are common in modern JavaScript, especially when passing short functions to other methods.
Now, what if we want to store several related values? An array gives us one ordered collection. JavaScript starts counting its indexes from zero, so index 0 refers to the first item.
const languages = ["HTML", "CSS", "JavaScript"];
console.log(languages[0]);
languages[1] = "CSS3";
languages.push("React");
const removedLanguage = languages.pop();
console.log(languages.length);
The .push() method adds an item to the end, .pop() removes the final item, and .length reports how many items the array contains. A const array can still have its contents changed; const prevents reassignment of the variable itself.
Next, let's repeat an action without copying the same line again and again. A for loop is useful when we need an index or precise control over the repetition:
for (let index = 0; index < languages.length; index++) {
console.log(languages[index]);
}
When you simply want to perform an action for every array item, forEach() provides a direct alternative:
languages.forEach(function (language) {
console.log(language);
});
Use the form that makes the task easiest to understand. A traditional loop exposes its starting point, condition, and increment. forEach() focuses on the current array item.
All right, now we can move beyond the console and change the actual webpage. The DOM represents the loaded HTML as objects JavaScript can access. First we select an element, and then we update its content or styles.
<h1>JavaScript Basics</h1>
<p id="message">Learning the DOM</p>
const heading = document.querySelector("h1");
const message = document.getElementById("message");
heading.textContent = "JavaScript is working!";
message.textContent = "The DOM has been updated.";
heading.style.color = "royalblue";
querySelector() accepts a CSS selector and returns the first match. getElementById() looks for one element using its ID without the # symbol.
Next, let's make the page respond to us. An event is something that happens in the browser, such as a click, key press, or form input. addEventListener() connects that event to a callback function.
const button = document.getElementById("action-button");
button.addEventListener("click", function () {
message.textContent = "The button was clicked.";
});
Note that the callback doesn't run immediately. The browser waits and calls it only when the selected event happens.
Now let's combine everything in a small counter project. The HTML gives us a number and three buttons:
<main style="text-align: center; font-family: Arial, sans-serif;">
<h1>JavaScript Counter</h1>
<p id="count" style="font-size: 3rem;">0</p>
<button id="decrease">Decrease</button>
<button id="reset">Reset</button>
<button id="increase">Increase</button>
</main>
In JavaScript, begin with one changing value and one function that synchronizes the visible number:
const countDisplay = document.getElementById("count");
let count = 0;
function updateDisplay() {
countDisplay.textContent = count;
}
Select the buttons and create one function for each action:
const increaseButton = document.getElementById("increase");
const decreaseButton = document.getElementById("decrease");
const resetButton = document.getElementById("reset");
function increaseCount() {
count++;
updateDisplay();
}
function decreaseCount() {
if (count > 0) {
count--;
}
updateDisplay();
}
function resetCount() {
count = 0;
updateDisplay();
}
Finally, let's connect each button to its function:
increaseButton.addEventListener("click", increaseCount);
decreaseButton.addEventListener("click", decreaseCount);
resetButton.addEventListener("click", resetCount);
And that's pretty much it. The count variable stores the current state, our functions contain the reusable behavior, the condition prevents negative values, textContent updates the page, and the click events run each action. As you can see, all the separate concepts now work together in one project.
If the page doesn't respond, don't worry. Check these details first:
script.js is spelled exactly the same in the filename and src attribute.defer when the script loads from the HTML head.addEventListener() without calling it immediately. Use increaseCount, not increaseCount().let only when reassignment is required, and use const for the remaining variables.All right, you now understand JavaScript values, variables, operators, conditions, functions, arrays, loops, objects, the DOM, and events. More importantly, you've seen how these concepts work together inside a complete interactive project.
The best next step is to build small projects. Every project gives you another reason to select elements, store state, respond to events, and divide behavior into functions. That's how the syntax starts feeling natural instead of looking like a list of rules.
if blockelse if conditionelse block