What you'll be able to do

By the end of this page you should be able to add, subtract, and compare values on purpose, know why = is not a comparison, and pick === for almost every “are these the same?” check. You will also see how == can quietly convert types and send an if down the wrong path without a red error.

Previous post: strings and template literals.

Who this is for

  • People who wrote if (score = 10) and could not see why the branch always ran
  • Beginners who compared a form value "5" with the number 5 and got two different answers from == and ===
  • Anyone who used + after a string and watched two numbers become "23" instead of 5

You can skip this if you already default to ===, you never assign inside an if, and you convert form strings before you do math. Come back when a check “looks true” in your head but the page does the other thing.

= stores. === asks. They are not cousins.

= puts a value into a name. === asks whether two values are the same type and the same value.

let score = 10;
console.log(score === 10);
console.log(score = 9);
console.log(score);

The first log is true. The second log is 9, because an assignment is the value you stored — and now score is 9.

Scenario A — a real check. if (score === 10) is “only continue if the score is the number ten.”

Scenario B — a typo that looks like a check. if (score = 10) sets score to 10, then the if sees 10, which JavaScript treats as “go ahead.” The branch always runs, the score is overwritten, and there is no crash. That is why this bug is so hard to spot in a long file.

Write === when you mean “are these equal?” Save = for the line where you create or update a variable.

Math operators you will actually type

These do what school math suggests, with one famous exception: +.

console.log(10 + 3);
console.log(10 - 3);
console.log(10 * 3);
console.log(10 / 4);
console.log(10 % 3);

% is remainder: 10 divided by 3 leaves 1. Useful for “every third item” or “is this even?” (n % 2 === 0).

Scenario A — a total. price quantity for a cart line. Keep both sides numbers. If quantity is still the string "2" from an input, "2" 3 happens to become 6 because * forces numbers — which looks fine until you switch to +.

Scenario B — the + trap you already met. "2" + 3 is "23". + adds when both sides are numbers, and concatenates as soon as one side is a string. Convert first: Number(raw) + 3, or put the math inside a template: Total: ${Number(raw) + 3}.

Compound updates are shorthand, not a new kind of math:

let count = 1;
count += 1;
count -= 1;

count += 1 means count = count + 1. Same leftover-+ rule: count += "1" will turn a number into a string if you are not careful.

Comparisons: bigger, smaller, and “is this in range?”

const age = 18;
console.log(age > 17);
console.log(age >= 18);
console.log(age < 18);
console.log(age <= 17);

Scenario A — a gate. Show an adult layout when age >= 18. Use >= when 18 should pass. Using > by accident locks out the exact boundary.

Scenario B — a range. A volume slider might need value >= 0 && value <= 100. && here means “both must be true.” We will go deeper on true/false-looking values in the next post; for now, treat && as “and” and || as “or” between comparisons you already understand.

! flips a boolean: if (!ready) is “if ready is false.” Do not write if (ready === false) out of fear — ! is the normal way once ready is actually a boolean.

=== vs ==: same value, or “close enough after conversion”

=== (strict equality) asks: same type, same value. == (loose equality) will convert types first, then compare. That conversion is where silent wrong branches come from.

console.log(5 === 5);
console.log(5 === "5");
console.log(5 == "5");

That is true, false, true. The last one is the surprise.

Scenario A — a form field. Inputs give strings. input.value === 5 is false even when the box shows 5, because "5" is not the number 5. Convert, then compare: Number(input.value) === 5, or compare strings to strings: input.value === "5". Pick one side and stick to it.

Scenario B — a flag that is not quite boolean. 0 == false is true. "" == false is true. null == undefined is true. === says false for all of those, which is usually what you wanted. If you write if (count == false) thinking you are testing a boolean, a real zero count will look like “false” and skip the branch that should show “0 items.”

The same split exists for “not equal”: !== is the strict one, != is the converting one. Prefer !==.

A practical default: use === and !== everywhere, and convert types in the open when you need to. == is not “shorter ===.” It is a different question.

A tiny practice file

Save as operators.html. Type 5, click the button, and read both results. Then try 05 and a blank box.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Operators</title>
  </head>
  <body>
    <input id="raw" placeholder="Type 5" />
    <button id="go">Compare to 5</button>
    <p id="out">Result will show here.</p>
    <script>
      const rawInput = document.getElementById("raw");
      const goButton = document.getElementById("go");
      const out = document.getElementById("out");

      goButton.addEventListener("click", function () {
        const raw = rawInput.value.trim();
        const asNumber = Number(raw);
        const loose = raw == 5;
        const strict = raw === 5;
        const strictAfter = asNumber === 5;
        out.textContent =
          "Loose == 5: " +
          loose +
          ". Strict === 5 (still a string): " +
          strict +
          ". Number(value) === 5: " +
          strictAfter;
      });
    </script>
  </body>
</html>

Typing 5 usually makes loose true and strict false, until you convert. A blank box makes Number("") into 0, so asNumber === 5 is false — another reminder that empty is not “missing math,” it is a conversion you have to notice.

Mistakes I see a lot

1. = inside if. That assigns. Use ===.

2. Comparing a form string to a number with === and calling it a bug in JavaScript. Convert first, or compare "5" to "5".

3. Using == because a tutorial from 2012 did. You inherit the conversions. === plus an honest Number(...) is easier to debug.

4. + after a string when you meant add. "Total: " + 2 + 3 is "Total: 23". Add in parentheses or inside ${}.

5. >= vs > on a boundary. If 18 should pass, write >= 18.

6. != when you meant !==. Same conversion surprises as ==.

What to try before the next post

  1. Log 5 === "5" and 5 == "5".
  2. Log 0 == false and 0 === false.
  3. Write if (score = 10) on purpose in the console, then fix it to ===.
  4. Build the tiny HTML file and try 5, 05, and a blank input.

Next in this series: truthy, falsy, and boolean coercion — why if (name) is not the same question as if (name === true).

Try this next outside the series

Values become easier when you see them inside real forms and payloads, not only tiny console lines.