What Is The Triple Equals Sign? (JS Strict Equality)
In JavaScript, === is the strict equality operator. It returns true when two values have the same type and are equal under JavaScript’s comparison rules. Unlike ==, it does not convert one value to another before comparing. It compares objects by identity, not by their contents, and has special behavior for NaN and signed zero.
A learner might ask, “Why does 5 === "5" say these values are different when they look alike?” That is a useful question: JavaScript cares about both a value’s type and its value when it uses strict equality. Knowing that distinction can help you spot bugs in conditions, tests, and form handling.
In the examples below, you can predict each result before running the code. I use small, focused scenarios because they make it easier to see what the operator actually checks.
What === means in JavaScript
The === operator compares two values without converting either one to match the other’s type. The result is always a Boolean value: true or false. For ordinary comparisons, both type and value must match. There are special rules for numbers and objects, which are explained below.
For example:
5 === 5 // true
5 === "5" // false
"cat" === "cat" // true
The first pair contains two Numbers with the same value. The second compares a Number with a String, so the result is false. The third compares two matching strings.
A Boolean result can control a conditional:
const score = 5;
if (score === 5) {
console.log("The score is five.");
}
Here, the condition is true, so the code inside the braces runs. If score were the string "5", the condition would be false. The operator does not silently change that string into a number.
How === differs from ==
Strict equality (===) checks without type conversion. Loose equality (==) may convert values before comparing them, according to JavaScript’s rules. That conversion can make unlike types compare as equal, so == may produce a result that is less clear at a glance.
| Expression | Result | Why |
|---|---|---|
5 === 5 |
true |
Same type and same number |
5 === "5" |
false |
Number and String differ |
5 == "5" |
true |
Loose equality converts for comparison |
false === 0 |
false |
Boolean and Number differ |
false == 0 |
true |
Loose equality converts for comparison |
null === undefined |
false |
They are distinct values |
null == undefined |
true |
This is a special loose-equality rule |
A common source of confusion is that == does not follow one simple “convert everything to a number” rule. Its behavior depends on the types being compared. For example, null == undefined is true, but null == 0 is false.
For everyday comparisons, === is usually easier to read because it avoids these implicit conversions. Use == only when you deliberately want its conversion rules and can explain why they are appropriate.
How strict equality handles types and values
JavaScript values have types, such as Number, String, Boolean, Object, and Undefined. A primitive is a value that is not an object, such as 7, "hello", or false. Strict equality compares primitives by type and value, while objects are compared by identity.
How primitive values compare
A primitive is compared with another primitive by its type and value. Two strings with the same characters compare as equal, as do two matching Booleans. A Number and a String do not become equal just because they look alike.
"cat" === "cat" // true
true === true // true
7 === 7 // true
7 === "7" // false
Variables do not change the rule. JavaScript compares the values held by the variables at the time the expression runs:
const first = "ready";
const second = "ready";
first === second // true
Both variables contain the same string value. If one instead held "Ready" with a capital letter, the strings would not match.
Why matching objects may not be equal
Objects, arrays, and functions are compared by identity. In plain terms, JavaScript checks whether both sides refer to the very same object, not whether they contain matching properties or items. Two separately created objects are distinct, even when their contents look identical.
{} === {} // false
const item = { id: 4 };
const sameItem = item;
item === sameItem // true
The two empty object literals create two different objects. By contrast, sameItem refers to the object already stored in item.
The same rule applies to arrays:
[1, 2] === [1, 2] // false
If you need to compare object contents, compare the relevant properties or use a suitable deep-equality method. A deep comparison checks values inside objects, but === itself does not. The right method depends on the data and the needs of your program.
Special cases: NaN, zero, null, and undefined
Most strict comparisons follow the type-and-value pattern, but several numeric and nullish cases deserve attention. In particular, NaN is not strictly equal to itself, positive and negative zero are strictly equal, and null and undefined remain different values under ===.
Why NaN === NaN is false
NaN is a special Number value that means “Not a Number,” often produced by an invalid numeric calculation. Its behavior is unusual: it is not equal to itself.
NaN === NaN // false
To check whether a value is NaN, use Number.isNaN():
Number.isNaN(NaN) // true
Number.isNaN("hello") // false
This method is more precise than relying on equality. It returns true for the actual NaN value, rather than treating other values as if they were NaN.
How 0 and -0 compare
JavaScript has both positive zero and negative zero as Number values. Strict equality treats them as equal:
0 === -0 // true
For most everyday code, this result is expected. If your program needs to tell them apart, Object.is() can do so:
Object.is(0, -0) // false
How null and undefined compare
null and undefined are distinct values, so strict equality keeps them separate. Each is equal to itself, but neither is strictly equal to the other.
null === null // true
undefined === undefined // true
null === undefined // false
This distinction can help you decide whether a value was intentionally set to “no value” (null) or was not provided or assigned (undefined). The meaning depends on how your program uses each value.
How to use strict equality in reliable code
For routine comparisons, use === and make any intended conversion explicit. This makes the code’s choices visible: a reader can see whether you are comparing a number with a number or first converting a value. Explicit steps also make debugging easier.
Suppose a form field supplies the text "42", but your code needs a Number:
const enteredText = "42";
const enteredNumber = Number(enteredText);
enteredNumber === 42 // true
The conversion is clear and separate from the comparison. Without it, "42" === 42 is false.
A practical sequence for checking a comparison is:
- Identify the type and value on each side.
- Predict whether
===should returntrueorfalse. - If types differ, decide whether conversion is actually intended.
- Convert explicitly when needed, then compare.
- Check special cases such as
NaNor separately created objects.
In a browser, you can enter expressions in the developer console and inspect the result. You can also add focused tests to your test suite. Testing both matching and nonmatching cases helps confirm that a condition does what you expect.
Common equality mistakes and debugging scenarios
A debugging scenario is a small, focused example that reveals why a comparison returned an unexpected result. These examples are not reports of actual incidents; they show how to trace the types, values, and references involved when strict equality gives a surprising answer.
Scenario: A numeric form value fails a check
const formValue = "5";
if (formValue === 5) {
console.log("Matched");
}
The message does not appear because formValue is a String and 5 is a Number. If the field should represent a number, convert and validate it before comparing:
const numberValue = Number(formValue);
if (numberValue === 5) {
console.log("Matched");
}
Conversion alone may not be enough for every input. Check that the converted value is valid for your use, and use Number.isNaN() when you need to detect an invalid numeric result.
Scenario: Two objects look the same but fail a test
const expected = { status: "ready" };
const actual = { status: "ready" };
expected === actual // false
Each object literal creates a separate object. If the test only needs to check the status, compare that property:
actual.status === expected.status // true
For larger objects, choose a deep-equality tool that suits your environment, or write a comparison for the specific fields that matter. Do not assume === checks nested contents.
Scenario: A NaN check never passes
const result = Number("not a number");
result === NaN // false
Even though result is NaN, equality with NaN returns false. Use the dedicated check instead:
Number.isNaN(result) // true
These scenarios share a useful debugging habit: inspect the actual values and their types before changing the operator. Replacing === with == may hide a type mismatch instead of fixing the underlying issue.
Frequently asked questions
These quick answers cover the points that most often cause confusion: what the operator returns, how it treats different types, and when another comparison method is needed. Use the examples to check your understanding, then test unfamiliar cases in a JavaScript console.
What does === mean in JavaScript?
=== means strict equality. It returns true when the values match under JavaScript’s strict-equality rules, without converting one value to another first. For primitives, type and value must match. Objects must be the same object reference.
What is the difference between === and ==?
=== compares without type conversion. == may convert values before comparing them, so 5 == "5" is true while 5 === "5" is false. Prefer strict equality for ordinary comparisons unless you intentionally need loose equality’s conversion behavior.
Does === compare object contents?
No. Strict equality compares objects by identity, meaning both sides must refer to the same object. Two separate objects with identical properties are not strictly equal. Compare the properties you care about, or use an appropriate deep-equality method.
Why is NaN === NaN false?
JavaScript defines NaN as unequal to every value, including itself. Use Number.isNaN(value) to check whether a value is NaN. This is the reliable test for that special numeric value.
Is 0 === -0 true?
Yes. Strict equality treats positive zero and negative zero as equal, so 0 === -0 returns true. If your code must distinguish the two, use Object.is(0, -0), which returns false.
Are null and undefined strictly equal?
No. null === undefined returns false because they are distinct values. Each is strictly equal to itself. Their loose comparison is different: null == undefined returns true under a special rule.
Does === always return a Boolean?
Yes. A strict-equality expression returns either true or false. Code can use that result directly in an if condition, assign it to a variable, or check it in a test.
Should I always use === instead of ==?
For ordinary comparisons, === is usually clearer because it avoids implicit type conversion. Use == only when its conversion behavior is intentional and understood. If you need a conversion, make it explicit before comparing.
When a comparison surprises you, check the type and value on each side first. Then check whether either side is an object, NaN, null, or undefined. Those steps explain most strict-equality results and point toward the right fix.
(This article was written by one of our staff writers, Nathan Sterling. Visit our Meet the Team page.)
