People look up javascript equals, javascript equality, equal javascript, and equality javascript for the same core topic: how the language decides whether two values “match.” In code you express that with the equal sign operators: a single pair == for loose equality, or === when you want strict equality (often what people mean when they type javascript === in a search). Understanding both helps you read older codebases and avoid subtle bugs.
Loose equality may apply type coercion so operands become comparable types. Strict equality compares both type and value without that conversion. For day‑to‑day logic, defaulting to === is the usual style guide recommendation; knowing == still matters when you read specs, minified libraries, or interviews.
Tested on: Node.js v20.18.2. A short note after each runnable snippet describes what you should see in the console.
Quick reference
| Operator | Coercion? | Typical use |
|---|---|---|
== |
Yes (abstract equality) | Rare; intentional null/undefined checks |
=== |
No | Default for primitives and reference identity |
Object.is |
No; SameValue |
NaN sameness, +0 vs -0 |
Types you compare with javascript equal and strict operators
Before comparing values, it helps to know what typeof reports. Strings, numbers, and booleans are primitives. Ordinary objects and arrays are both of type "object" in this check.
const str = 'JavaScript equals can be challenging.';
console.log(typeof str);
const myIntNumber = 15;
const myDoubleDiscount = 15.93;
console.log(typeof myIntNumber);
console.log(typeof myDoubleDiscount);
const literal = { a: 3, b: 7 };
const array = ['string', 19, true];
console.log(typeof literal, typeof array);You should see four lines: string, two number lines, then object object.
Wrapping a primitive in new String, new Number, or new Boolean produces an object wrapper. That distinction shows up immediately under typeof, and it also affects how == coerces values.
const stringLiteral = 'I like to compare strings.';
const stringObject = new String('I like to compare strings.');
const numberLiteral = 89;
const numberObject = new Number(89);
console.log(typeof stringLiteral);
console.log(typeof stringObject);
console.log(typeof numberLiteral);
console.log(typeof numberObject);
const booleanLiteral = false;
const booleanObject = new Boolean(null);
console.log(typeof booleanLiteral);
console.log(typeof booleanObject);You should see alternating string / object, number / object, and boolean / object—literals stay primitives; wrappers report object.
Custom constructors behave like other objects: the instance is an object, while a plain string literal stays a string.
function Person(name) {
this.name = name;
}
const personLiteral = 'John Doe';
const personObject = new Person('John Doe');
console.log(typeof personLiteral);
console.log(typeof personObject);You should see string then object.
Truthiness still drives if statements; for a refresher on empty collections, see check if a JavaScript array is empty.
Loose equality when types already match
With the same types and no coercion path, == behaves like common sense: strings compare by character sequence and casing, numbers by numeric value, booleans by their true or false value.
console.log('doe' == 'doe');
console.log('doe' == 'Doe');You should see true then false.
console.log(3 == 3);
console.log(3 == 13);You should see true then false.
console.log(false == false);
console.log(true == false);You should see true then false.
When javascript equality converts operands
Strings compared to numbers
If one side is a string and the other a number, the string is converted to a number (or to NaN if it is not numeric) before the numeric comparison.
console.log(17 == '17');
console.log(17 == '37');You should see true then false.
Boxed numbers against primitives
Object wrappers participate in the abstract equality algorithm: the object is coerced to its primitive value before comparison.
const numObject = new Number(97);
const numPrimitive = 97;
console.log(numObject == numPrimitive);You should see true.
Booleans mixed with numbers
If either operand is a boolean, it is first converted to a number (true to 1, false to 0) before the rest of the comparison runs.
console.log(true == 1);
console.log(0 == false);
console.log(true == 19);You should see true, true, then false.
null, undefined, and a common pitfall
null and undefined are only loosely equal to each other, not to other types such as numbers.
console.log(null == undefined);
console.log(null === undefined);
console.log(null == 0);You should see true, false, false.
So null == undefined is true, but null === undefined is false, and null == 0 is false even though 0 == false is true—the algorithms are different branches.
Strict equality: the javascript equal sign pair ===
Strict equality, written with three equal signs, skips type conversion. Both type and value must already line up.
console.log(17 === '17');
console.log(17 === 17);
console.log(0 === false);You should see false, true, false.
That is why searches for javascript === land on this operator: it is the straightforward “same type and same value” check for primitives and object identity.
Why NaN === NaN is false (and how Object.is helps)
IEEE‑754 NaN is not equal to itself under strict equality, which surprises readers who expect “equals javascript” to behave symmetrically for every numeric edge case.
console.log(NaN === NaN);
console.log(Object.is(NaN, NaN));You should see false then true.
Object.is follows SameValue semantics and treats two NaN values as a match, while still distinguishing +0 and -0 unlike ===.
Practical guidance
Default to === for application logic so equality javascript checks stay predictable. Reserve == for cases you truly intend to coerce, such as comparing against null and undefined together with (value == null), which some teams use as a shorthand for “either nullish value.” Document that pattern in code review so future readers know it was deliberate.
Summary
Use === by default; use == only when coercion is intentional; use Object.is when NaN or signed zero matter.
JavaScript equality questions usually start with javascript === versus loose equals javascript: strict equality === compares without coercion, while == applies the abstract equality comparison rules that surprise teams when "0" meets 0. Default to === for application logic, and reserve == for the narrow cases you truly intend to coerce—(value == null) is the most common intentional pattern because it matches both null and undefined.
Readers also ask why NaN === NaN is false and how Object.is differs: Object.is uses SameValue semantics, so two NaN values match while +0 and -0 remain distinguishable, which matters for certain math and animation code paths. When edge cases pile up, MDN’s equality comparisons and sameness guide is the authoritative cheat sheet.
Further reading
- Equality (
==) — MDN - Strict equality (
===) — MDN - Equality comparisons and sameness — MDN

