Compare strings in JavaScript: ===, localeCompare, and case-insensitive matches

JavaScript string compare and string equals with === vs ==, localeCompare and Intl.Collator for locale-aware sorting, case-insensitive patterns, trim and Unicode normalize—with example console output.

Published

Updated

Read time 6 min read

Reviewed byDeepak Prasad

Compare strings in JavaScript: ===, localeCompare, and case-insensitive matches

Comparing text in JavaScript sounds trivial until you mix types, locales, or Unicode. You might need strict equality between two strings, locale-aware sort order, or a case-insensitive match that still behaves in Turkish, German, or mixed scripts. The wrong tool—usually == or plain toLowerCase()—quietly passes tests in English and fails in production.

Here you will start from === for two strings, see why == is risky when inputs are not guaranteed to be strings, then use localeCompare and Intl.Collator when collation matters. We also cover trim, normalize, and a short character scan example.

Tested on: Node.js v20.18.2. After each snippet, a short note describes the values or lines you should see in the console.


Quick reference

Use this table for javascript compare strings and compare strings js tasks.

Goal Approach
Same string value, same case a === b (both strings)
Avoid coercion bugs Prefer ===, not ==
Sort / locale-aware equality localeCompare or Intl.Collator with locale + sensitivity
Ignore surrounding whitespace a.trim() === b.trim() (and same normalization strategy)
Unicode “looks equal” normalize("NFC") (or another form), then ===

1. javascript string equals — use ===

For two values that are already strings, === is the usual javascript string compare for equality: same characters, same case, no type conversion.

javascript
const str1 = "hello";
const str2 = "hello";

if (str1 === str2) {
  console.log("The strings are equal");
} else {
  console.log("The strings are not equal");
}
Output

You should see The strings are equal.


2. Avoid == for compare strings js (type coercion)

Loose equality == converts operands so "1" and 1 can look “equal,” which is rarely what you want when you care about compare string javascript semantics for text:

javascript
const str1 = "1";
const str2 = 1;

if (str1 == str2) {
  console.log("The strings are equal");
} else {
  console.log("The strings are not equal");
}
Output

With ==, you should see The strings are equal even though one operand is a string and one is a number.

The same pair with === shows the safer behavior for mixed types:

javascript
const str1 = "1";
const str2 = 1;

if (str1 === str2) {
  console.log("The strings are equal");
} else {
  console.log("The strings are not equal");
}
Output

With ===, you should see The strings are not equal for "1" versus 1.


3. localeCompare — sort order and “equal under locale rules”

localeCompare does not simply compare raw Unicode code units; it follows collation rules for the locale and options you provide (see MDN localeCompare). A return value of 0 means “equivalent” for that configuration; the sign tells you javascript compare string ordering for sorting.

javascript
const str1 = "hello";
const str2 = "world";
const result = str1.localeCompare(str2);

if (result === 0) {
  console.log("The strings are equal");
} else if (result < 0) {
  console.log("The first string comes before the second string");
} else {
  console.log("The first string comes after the second string");
}
Output

Because "hello" sorts before "world" in default collation, you should see The first string comes before the second string.

Equality under default options (case-sensitive here):

javascript
console.log("result:", "hello".localeCompare("hello"));
Output

You should see result: 0—two identical strings compare as equivalent under default options.


4. Case-insensitive js compare strings with localeCompare

For javascript string compare when case should be ignored (English example), sensitivity: "base" treats base letters as the same regardless of case:

javascript
console.log(
  "A vs a (sensitivity base):",
  "A".localeCompare("a", "en", { sensitivity: "base" }),
);
Output

You should see a line like A vs a (sensitivity base): 0—the trailing 0 means the two strings are equivalent under that locale and options.

Locale matters: with the default locale, Latin I and i often compare as case-insensitive under sensitivity: "accent", but Turkish rules differ:

javascript
console.log(
  "default accent I vs i:",
  "I".localeCompare("i", undefined, { sensitivity: "accent" }) === 0,
);
console.log(
  "tr accent I vs i:",
  "I".localeCompare("i", "tr", { sensitivity: "accent" }) === 0,
);
Output

First line prints default accent I vs i: true under the default locale; the Turkish line prints tr accent I vs i: false, illustrating locale-sensitive casing rules.

That is why MDN recommends localeCompare / Intl.Collator over naive toLowerCase() for i18n (see MDN: comparing strings).

English-only quick check with case folding (fine until you leave simple ASCII):

javascript
console.log(
  "Hello vs hello (toLowerCase):",
  "Hello".toLowerCase() === "hello".toLowerCase(),
);
Output

You should see Hello vs hello (toLowerCase): true.


5. Intl.Collator — same ideas as localeCompare

Intl.Collator is the dedicated API for comparisons; localeCompare is specified to align with it in modern engines. Example for compare strings javascript equality ignoring case in English:

javascript
const collator = new Intl.Collator("en", { sensitivity: "base" });
console.log("Collator compare A,a:", collator.compare("A", "a"));
Output

collator.compare returns 0 for equivalent letters under sensitivity: "base", so the log shows Collator compare A,a: 0.


6. User input: trim and Unicode normalize

Surrounding spaces break naive ===; trim() fixes the common case:

javascript
const a = "  hi  ";
const b = "hi";
console.log(a.trim() === b);
Output

After trimming, the comparison is true.

Visually identical text can use different code point sequences. normalize("NFC") is a typical fix before javascript string equals:

javascript
const a = "café";
const b = "cafe\u0301";
console.log("raw ===", a === b);
console.log("NFC ===", a.normalize("NFC") === b.normalize("NFC"));
Output

You should see raw === false (different code point sequences) and NFC === true once both sides are normalized the same way.


7. Character-by-character check (rare)

You can scan with charAt or indexed access; for plain UTF-16 strings === already compares the full sequence, so this is mostly a teaching pattern unless you add custom early-exit logic:

javascript
let str1 = "hello";
let str2 = "Hello";

if (str1.length !== str2.length) {
  console.log("The strings are not equal");
} else {
  let isEqual = true;
  for (let i = 0; i < str1.length; i++) {
    if (str1.charAt(i) !== str2.charAt(i)) {
      isEqual = false;
      break;
    }
  }
  if (isEqual) {
    console.log("The strings are equal");
  } else {
    console.log("The strings are not equal");
  }
}
Output

Case-sensitive character comparison finds a mismatch on the first letter, so you should see The strings are not equal.


Summary

  • Prefer === for real string equality; avoid == when types can vary.
  • Use localeCompare / Intl.Collator with explicit locale and sensitivity for collation and case folding beyond ASCII.
  • Normalize Unicode and trim whitespace before comparing user-facing text.

References

MDN references for equality, localeCompare, Intl.Collator, and string comparison guidance.


Frequently Asked Questions

1. What is the default way to check javascript string equals?

Use the strict equality operator === between two string values. It compares both value and type, does not coerce types, and compares strings case-sensitively.

2. Is javascript string compare case sensitive with === and < operators?

Yes. For case-insensitive equality, do not rely only on toLowerCase in every language; prefer localeCompare or Intl.Collator with an explicit locale and sensitivity options when correctness matters.

3. What does localeCompare return?

A negative number if the reference string sorts before the other, a positive number if it sorts after, and 0 if they are considered equivalent under the locale and options you pass.

4. Should I use == or === to compare strings javascript?

Prefer ===. == applies type coercion, so values like "1" and 1 can be reported as equal, which is usually wrong when you meant two strings.

5. How do I do case insensitive string compare in js string compare scenarios?

One robust approach is str1.localeCompare(str2, locale, { sensitivity: "base" }) === 0 (or sensitivity accent depending on whether accents must differ). Intl.Collator with the same sensitivity is equivalent in spirit.

6. Why might two visually identical strings fail ===?

Different Unicode representations (for example precomposed café versus e plus a combining accent) compare unequal until you normalize both sides, often with normalize("NFC").
Olorunfemi Akinlua

Boasting over five years of experience in JavaScript, specializing in technical content writing and UX design. With a keen focus on programming languages, he crafts compelling content and designs …