The operators introduction covers the four families that make JavaScript do things: arithmetic, assignment, comparison, and logical, plus the ternary shortcut and the truthiness rules that power real-world defaults. This workbook runs each one. The single most important habit it builds is in Example 6: always use ===, and forget == exists.
<html lang="en"><head> <meta charset="utf-8"> <script src="script.js" defer></script></head><body> <p>Open the console to see the output.</p></body></html>
1. Arithmetic operators
The five arithmetic operators work exactly as you would expect, with one newcomer: %, the modulo, which returns the remainder of a division.
let x = 10;let y = 3;console.log(x + y); // 13console.log(x - y); // 7console.log(x * y); // 30console.log(x / y); // 3.3333333333333335console.log(x % y); // 1, the remainder of 10 / 3
Four of these you have used since primary school. The modulo is the one to sit with: 10 divided by 3 is 3 remainder 1, and % hands you that 1. It looks obscure now, but Example 2 shows why it earns its keep.
2. What modulo is actually for
Modulo answers two questions that come up constantly: “does this divide evenly?” and “how do I cycle through a fixed set?”
// even or odd: a number is even when the remainder of / 2 is 0console.log(8 % 2); // 0, so 8 is evenconsole.log(9 % 2); // 1, so 9 is odd// cycling: wrap any counter into a fixed rangeconst days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];console.log(days[8 % 7]); // 'Tue', day 8 wraps to index 1console.log(days[14 % 7]); // 'Mon', day 14 wraps to index 0
The evenness check powers things like striping alternate table rows, and the cycling trick keeps any growing counter locked inside the bounds of an array. When you see % in real code, it is almost always doing one of these two jobs.
3. Increment and decrement: prefix versus postfix
++ adds one and -- subtracts one, but where you put them changes what you get back. Prefix updates first and then hands you the new value; postfix hands you the current value and then updates.
let a = 5;console.log(++a); // 6: increment FIRST, then give the valueconsole.log(a); // 6let b = 5;console.log(b++); // 5: give the current value FIRST, then incrementconsole.log(b); // 6
Both a and b end up at 6; the difference is only what the expression itself reported at the moment of use. In practice most code uses these on their own line, counter++;, where the distinction cannot bite. The trap only opens when you use the result inline, so if you remember one thing, remember to be careful exactly there.
4. Assignment operators
Compound assignments fold an arithmetic operation into the assignment. x += 5 reads as “add 5 to x”, and every arithmetic operator has a matching version.
let score = 10;score += 5; // score = score + 5 -> 15score -= 3; // score = score - 3 -> 12score *= 2; // score = score * 2 -> 24score /= 4; // score = score / 4 -> 6score %= 4; // score = score % 4 -> 2console.log(score); // 2
Each line rewrites the variable using its own current value. The compound forms are pure convenience, but they are the convention you will see everywhere, so it pays to read += as fluently as =.
5. Comparison operators
Comparisons return a boolean, true or false, which is what makes decisions possible. The relational four are straightforward.
let points = 120;console.log(points > 100); // trueconsole.log(points >= 120); // trueconsole.log(points < 100); // falseconsole.log(points <= 119); // false// the result is a value you can store like any otherconst qualifies = points > 100;console.log(qualifies); // true
The last two lines carry the insight: a comparison is not just something you put inside an if. It produces a value you can name, store, and pass around, which is how readable code turns a condition like points > 100 into a variable called qualifies.
6. Strict versus loose equality
JavaScript has two equality operators, and this example is the reason the guide says to use only one of them. Loose ==converts types before comparing; strict === compares value and type, no conversions.
console.log('1' == 1); // true! loose equality coerced the stringconsole.log('1' === 1); // false: different types, so not equalconsole.log(0 == false); // true! more coercion surprisesconsole.log(0 === false); // falseconsole.log(5 === 5); // true: same type, same valueconsole.log('5' !== 5); // true: the strict not-equal partner
Loose equality’s conversions follow rules almost nobody remembers, which makes == a bug generator: your code appears to work until a string-shaped number arrives from a form field. The rule to adopt today and never revisit: always === and !==, and forget == exists.
7. The ternary operator
The ternary is a one-line decision: a condition, a question mark, the value if true, a colon, the value if false. It shines when you would otherwise write four lines of if/else just to assign a variable.
let points = 120;const tier = points > 100 ? 'gold' : 'silver';console.log(tier); // 'gold'// exactly equivalent to:// let tier;// if (points > 100) { tier = 'gold'; } else { tier = 'silver'; }const delivery = points > 100 ? 0 : 4.99;console.log('Delivery: £' + delivery); // Delivery: £0
Read ? as “then” and : as “otherwise” and every ternary becomes a sentence: points above 100, then gold, otherwise silver. Keep them to single, simple decisions; nested ternaries are legal but unreadable, and that is what if/else is for.
8. Logical operators
&&, ||, and ! combine booleans. AND needs both sides true, OR needs at least one, and NOT flips whatever it is given.
const hasAccount = true;const isVerified = false;console.log(hasAccount && isVerified); // false: AND needs bothconsole.log(hasAccount || isVerified); // true: OR needs oneconsole.log(!isVerified); // true: NOT flips it// combining into a real ruleconst age = 24;const income = 32000;const eligible = age >= 21 && income > 25000;console.log(eligible); // true
The last block is the practical shape: comparisons on either side, glued by && into a single business rule you can name. One character matters here, since single & and | also exist as bitwise operators that work on binary digits; for everyday logic you always want the doubled forms.
9. Truthiness and the OR default pattern
JavaScript treats every value as either truthy or falsy when a boolean is needed. Exactly six values are falsy: false, 0, '', null, undefined, and NaN. Everything else is truthy, and || exploits this to provide fallbacks.
// || returns the FIRST truthy value it findslet userColor; // undefined: the user chose nothingconst defaultColor = 'steelblue';const currentColor = userColor || defaultColor;console.log(currentColor); // 'steelblue'userColor = 'coral';console.log(userColor || defaultColor); // 'coral': user choice wins// beware: falsy values you meant to keep also trigger the fallbackconst quantity = 0;console.log(quantity || 10); // 10, even though 0 was a real answer!
value || fallback is one of the most common idioms in JavaScript: use the value if it is truthy, otherwise the fallback. The last line shows its sharp edge, since a legitimate 0 or empty string counts as falsy and gets replaced. Modern JavaScript adds ??for exactly that case, but the || pattern is the one you will meet in almost every codebase.
10. Putting it together: a loan eligibility checker
The finale combines every family: arithmetic to compute a ratio, comparisons and logicals to build the rule, a ternary to phrase the outcome, and modulo to generate a reference number.
const applicantAge = 29;const annualIncome = 34000;const loanAmount = 12000;const existingDebt = 4000;// arithmetic: how big is the loan relative to income?const loanRatio = loanAmount / annualIncome;const totalExposure = loanAmount + existingDebt;// comparison + logical: the eligibility rule in one lineconst eligible = applicantAge >= 21 && loanRatio < 0.5 && totalExposure <= annualIncome * 0.6;// ternary: turn the boolean into a decisionconst decision = eligible ? 'approved' : 'declined';// modulo + arithmetic: a 4-digit reference from the inputsconst reference = (applicantAge * loanAmount + annualIncome) % 10000;console.log('Loan ratio: ' + loanRatio.toFixed(2)); // 0.35console.log('Decision: ' + decision); // approvedconsole.log('Reference: LN-' + reference); // LN-2000
Walk the chain: arithmetic produced the numbers, comparisons turned them into booleans, && fused three requirements into one rule, the ternary translated the rule into a word, and modulo squeezed a reference number into four digits. No single operator did anything clever, and that is the point: real logic is ordinary operators composed carefully.
Work through these ten and you have the full toolkit from the article: arithmetic with a working understanding of modulo, prefix versus postfix increments, compound assignment, comparisons, strict equality as a reflex, the ternary, logical operators, truthiness with the OR default, and one realistic composition. The next step in the series puts these operators in charge of program flow: control flow and loops, where the booleans you built here start deciding which code runs.
See you soon, Andrei.
[…] JavaScript Operators: 10 Code-Along Examples […]
[…] Code along: https://datalad.co.uk/javascript-operators-10-code-along-examples/ […]
[…] For the full background, read the guide to JavaScript operators. To practise, work through the 10 code-along examples. […]