1112

What is the correct way to check for equality between Strings in JavaScript?

Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345
JSS
  • 11,137
  • 3
  • 16
  • 3
  • 7
    Is there a reason not to use == ? – Kendrick Aug 27 '10 at 17:41
  • 29
    @Kendrick -- sure. It's type-coercion system can be incredibly unintuitive and can make errors very easy to overlook (it *looks* right, but can be very wrong) – STW Aug 27 '10 at 17:42
  • 28
    @Kendrick - because `{} == "[object Object]"` evaluates to true, for example. – Chetan S Aug 27 '10 at 17:48
  • 22
    somewhat annoying that `String().equals()` is not a method in JS... – Alexander Mills Oct 06 '17 at 23:53
  • @Kendrick : `$$=='function $$(selector, [startNode]) { [Command Line API] }'` is true, because of JS code reflection – Agnius Vasiliauskas Mar 23 '18 at 20:13
  • 2
    @AlexanderMills Why? – Ry- Oct 07 '18 at 21:21
  • @Kendrick - yes - look on [this pictures](https://stackoverflow.com/a/63235980/860099) – Kamil Kiełczewski Dec 09 '20 at 08:00
  • For a little more context there are multiple ways to create Strings, and the equality behavior varies. There are string literals like `"this is a literal"`, there are objects like `new String("this is an object")`, and there is the `String()` function which does conversion `String(something)`. Generally you'll see string literals more than the others--but before you can really answer "how do I check equality" you have to know what you're dealing with. – STW Feb 10 '21 at 17:28

10 Answers10

792

always Until you fully understand the differences and implications of using the == and === operators, use the === operator since it will save you from obscure (non-obvious) bugs and WTFs. The "regular" == operator can have very unexpected results due to the type-coercion internally, so using === is always the recommended approach.

For insight into this, and other "good vs. bad" parts of Javascript read up on Mr. Douglas Crockford and his work. There's a great Google Tech Talk where he summarizes lots of good info: http://www.youtube.com/watch?v=hQVTIJBZook


Update:

The You Don't Know JS series by Kyle Simpson is excellent (and free to read online). The series goes into the commonly misunderstood areas of the language and explains the "bad parts" that Crockford suggests you avoid. By understanding them you can make proper use of them and avoid the pitfalls.

The "Up & Going" book includes a section on Equality, with this specific summary of when to use the loose (==) vs strict (===) operators:

To boil down a whole lot of details to a few simple takeaways, and help you know whether to use == or === in various situations, here are my simple rules:

  • If either value (aka side) in a comparison could be the true or false value, avoid == and use ===.
  • If either value in a comparison could be of these specific values (0, "", or [] -- empty array), avoid == and use ===.
  • In all other cases, you're safe to use ==. Not only is it safe, but in many cases it simplifies your code in a way that improves readability.

I still recommend Crockford's talk for developers who don't want to invest the time to really understand Javascript—it's good advice for a developer who only occasionally works in Javascript.

STW
  • 44,917
  • 17
  • 105
  • 161
  • 8
    It's not necessary when you're sure both operands are string, e.g., when using `if (typeof foo == "string")` – Marcel Korpel Aug 27 '10 at 17:43
  • 38
    @Marcel -- you're correct, but it's much better to *always* use the `===` operator and never have to worry about the "am I really, totally, 100% certain that `==` will behave how I think it will?" – STW Aug 27 '10 at 17:44
  • 1
    There are certain cases where it will *always* be a string, making `===` and its (infinitesimal) performance impact unnecessary. One is `typeof`, which is guaranteed to return a string. Another case off the top of my head is when you are iterating over a set of keys in an object -- of course, it also matters what you're comparing it to. These are cases where you don't have to "think" because it's guaranteed. I think for a beginner, it's not a bad idea to use `===`, but if you're experienced and know the spec well, you can forgo using `===` without risk. – Cristian Sanchez Aug 27 '10 at 17:55
  • And there are also cases where type coercion is a *good thing*. An example would be when comparing user input from some form element, which is always retrieved as a string, to a number. There are others. Treating `==` and type coercion as some kind of evil bug is bad practice I think. – MooGoo Aug 27 '10 at 18:40
  • 7
    @STW – one example why Crockford is not the alpha and omega of JavaScript, is his advice not to use unary increment/decrement (`++`/`--`). – Marcel Korpel Aug 27 '10 at 19:28
  • 11
    And never use `++` or `--` or single line `if/else` statements or `continue` or the `new` operator or any other number of perfectly legitimate code practices that Crockford has deemed "harmful". And of course never *ever* even consider thinking about using `eval` or `with` even if their pitfalls are well understood. And have you seen the next version of JS? Stricter syntax and a handful of helper functions, some which have been floating around for years, is about all we get after all this time. The syntax has not evolved at all. If Crockford is behind this, then it has been a bad thing. – MooGoo Aug 27 '10 at 19:35
  • Oh yes, but that's not dependent on Stack Overflow. But your corrections improve this answer, so +1. – Marcel Korpel Aug 28 '10 at 11:13
  • 1
    Crockford has really good ideas and valid reasons for his ideas, but at the end of the day, YOU are the programmer. It's always good to take your cigar-smoking methodology advice from an expert, but don't forget to think for yourself. Smoke it backwards if that's what suits your situation. – L0j1k Mar 28 '13 at 01:55
  • I think this is not 100% true for strings. I think one of them is not case sensitive while the other is... – PositiveGuy May 30 '13 at 18:28
  • 5
    @CoffeeAddict -- a quick test in JSFiddle appears to disagree. They are both case-sensitive: http://jsfiddle.net/st2EU/ – STW May 30 '13 at 18:35
  • I have been writing JavaScript for years, and every time I see people use `===` in places where you'd obviously expect the good old `==`, it always surprises me negatively. And surprises like this when reading code are invariably bad, no matter how JavaScript's peculiarities are, which I won't deny are many, compared to another language where use of `==` would be obvious. So for the sake of not tripping up people reading your code, and rest assured if `==` doesn't work for you chances are you have much bigger problems than you thought -- just use `==` and stop being a smart-ass. – Armen Michaeli May 13 '19 at 09:07
  • My point is contrary to the advice presented in this answer -- if you aren't really sure how `===` works, don't use it and even if you do, consider people trying to understand your logic when reading your code -- stick to the much more familiar to most `==` operator. `===` is only ever really useful in really fundamental levels of code where you'd need actual object reference comparison for things to work. If JavaScript were designed differently, perhaps one could have avoided this debate altogether, alas it is not the case, but fact of the matter is that `===` is tripping people up. – Armen Michaeli May 13 '19 at 09:10
  • 2
    @amn Many modern conventions actually advise developers to stick to the strict equality operator `===` (e.g. [ESLint's `eqeqeq` rule](https://eslint.org/docs/rules/eqeqeq)). The way I see it, the behavior of `==` making implicit conversions before the actual comparison is what trips people up. When coming from different languages, `==` is only familiar in syntax, not in semantics. Nevertheless, that seems to be just another opinion, and your choice of words here was too strong just for exposing an opinion. – E_net4 May 13 '19 at 10:00
  • The question has a specific context: "correct way to check for equality between Strings in JavaScript". And this answer, as it is now, does a _general_ discussion about difference between `==` and `===`, "good or bad" parts of Javascript, has some links to additional info, but states exactly _nothing_ about _correct way of __string__ equality check_. -1 for losing the specific _string_ context of a question. Have a look for @Anurag answer. – Andrii M4n0w4R Jul 23 '20 at 11:05
  • @STW regarding this incredible advice. **Does it also apply to integer equalities?** Thanks, TY bounty sent – Fattie Aug 04 '22 at 15:17
  • 1
    @Fattie if you're certain that both values being compared are integers then whether you use `==` or `===` doesn't matter. With javascript often you can't be 100% certain of the actual type, so it's a good habit to use the `===` operator since it generally behaves how engineers expect equality to behave whereas `==` can be confusing with some of its nuances – STW Aug 09 '22 at 15:13
  • @STW Got it. Yes, I absolutely understood your explanation: *"it's a good habit to use since behavior is more understandable"*. Totally. I just wanted to be sure that same concept (ie: *"it's a good habit to use since behavior is more understandable"*) applies when dealing with ints! TY !! – Fattie Aug 09 '22 at 15:24
  • I get the sentiment of wanting to understand the ugly parts of JavaScript instead of fearing and avoiding them (today's standard practice), but 1. Those bullet points are incomplete. They allow, and maybe even encourage comparisons like `2 == [2]` or `new Map() == '[object Map]'`. This means 2. You'll need a larger ruleset to properly tame `==` (have fun teaching that), and 3. (debatable) Are the "proper" uses of `==` (e.g. `num == str`) actually better? Yes, it's more concise compared to `String(num) === str`, but you lose valuable information which makes the code author's intentions clearer. – Scotty Jamison Aug 28 '22 at 20:23
258

If you know they are strings, then there's no need to check for type.

"a" == "b"

However, note that string objects will not be equal.

new String("a") == new String("a")

will return false.

Call the valueOf() method to convert it to a primitive for String objects,

new String("a").valueOf() == new String("a").valueOf()

will return true

Anurag
  • 140,337
  • 36
  • 221
  • 257
  • you mean `new String("a") == new String("a")` will return false? what about `new String("a") === new String("b")`? – JSS Aug 27 '10 at 17:41
  • 5
    thank for that JSS, two string objects will never be equal unless they are the same object regardless of the value. – Anurag Aug 27 '10 at 17:43
  • 6
    @JSS: Additionally, `new String("a") == "a"` is true (but wouldn't be with `===`), because the left hand side will be converted into a primitive string value. – Matthew Crumley Aug 27 '10 at 18:27
  • 6
    @JSS: `new String("a") == new String("a")`, `new String("a") === new String("b")`, `new String("a") === new String("a")` will all return `false`, since you're dealing with references to objects of the `String` class, not primitives of type `string`. – palswim Aug 27 '10 at 18:39
  • 10
    Just to clarify this for anyone reading it. `new String(foo)` creates a string *object*, and `String(foo)` *converts* foo to a string primitive. – Brigand Aug 30 '13 at 16:31
  • 12
    @FakeRainBrigand - clear as mud, but that's what javascripts about, isn't it? – Periata Breatta Sep 30 '16 at 07:28
96

You can use == or === but last one works in more simple way (src)

a == b (and its negation !=)

enter image description here

a === b (and its negation !==)

enter image description here

Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345
88

Just one addition to answers: If all these methods return false, even if strings seem to be equal, it is possible that there is a whitespace to the left and or right of one string. So, just put a .trim() at the end of strings before comparing:

if(s1.trim() === s2.trim())
{
    // your code
}

I have lost hours trying to figure out what is wrong. Hope this will help to someone!

akelec
  • 3,797
  • 3
  • 41
  • 39
  • 1
    Thanks a lot. It is strange to me though, because I made sure there was no whitespace to the left or right and still this was the only way to solve my problem. Maybe it is related to the internal representation of a string? – Niko Feb 12 '18 at 07:41
  • 2
    Thanks @akelec!! @Niko, it was likely due to the Zero-Width-Space character which is invisible to the naked eye. See https://en.wikipedia.org/wiki/Zero-width_space. Even though this character has its purposes, many developers resent its existence! – stwr667 Feb 19 '18 at 12:41
  • 1
    Thank you that was frustrating since the equality check in my if was failing yet I saw no whitespace when inspecting while debugging. – drzounds Oct 04 '18 at 03:29
  • A common problem when loading a variable from a text file (i.e: using `fetch`). Thanks a lot. – Sopalajo de Arrierez Nov 26 '19 at 21:27
  • This is the best answer. – Anayo Oleru Aug 08 '20 at 11:28
  • thnx for actually answering the question hahaha – Kröw May 07 '21 at 04:27
  • And then there are Unicode whitespace that `.trim()` doesn't find. Use `.strip()` instead. Even then, it misses `"\uC2A0"` and `"\\h"`. Even then, Unicode equivalence requires `.normalize()` since encoding varies. – AtesComp Dec 28 '21 at 22:52
  • Note that `trim` also creates a new **primitive**, so even in the absence of any non-printable characters, it does a type coercion that can change the behavior: `new String('hello') !== 'hello'` but `new String('hello').trim() === 'hello'` – Eric Haynes Jun 10 '22 at 19:47
  • −1. This has nothing to do with string equality. You are talking about one way of defining string equivalence in some specific regard. You could just as well talk about a myriad of other caveats, such as invisible characters, case, or combining characters. This is off-topic. – Philippe-André Lorin Jan 24 '23 at 09:41
31

what led me to this question is the padding and white-spaces

check my case

 if (title === "LastName")
      doSomething();

and title was " LastName"

enter image description here

so maybe you have to use trim function like this

var title = $(this).text().trim();
Basheer AL-MOMANI
  • 14,473
  • 9
  • 96
  • 92
  • 2
    Thanks same here I used `.toString().trim()` in Typescript – Akitha_MJ Jan 08 '19 at 18:15
  • 1
    How is this an answer to anything? – user3840170 Nov 16 '22 at 18:57
  • −1. This has nothing to do with string equality. You are talking about one way of defining string equivalence in some specific regard. You could just as well talk about a myriad of other caveats, such as invisible characters, case, or combining characters. This is off-topic. Plus, your wording is unclear. – Philippe-André Lorin Jan 24 '23 at 09:39
17

There are actually two ways in which strings can be made in javascript.

  1. var str = 'Javascript'; This creates a primitive string value.

  2. var obj = new String('Javascript'); This creates a wrapper object of type String.

    typeof str // string
    typeof obj // object

So the best way to check for equality is using the === operator because it checks value as well as type of both operands.

If you want to check for equality between two objects then using String.prototype.valueOf is the correct way.

new String('javascript').valueOf() == new String('javascript').valueOf()
Abhishek
  • 1,216
  • 1
  • 9
  • 13
9

String Objects can be checked using JSON.stringify() trick.

var me = new String("me");
var you = new String("me");
var isEquel = JSON.stringify(me) === JSON.stringify(you);
console.log(isEquel);
Dunc
  • 18,404
  • 6
  • 86
  • 103
Muhammad Usman
  • 863
  • 1
  • 11
  • 18
  • You are kidding right? Did you meant iSequel ;) Just kidding... – Sebastien Chartier Apr 30 '21 at 01:58
  • Although it works, it is not recommended, as it's a really time consuming operation. This solution should only be chosen if nothing else works. So, be aware in your future developments :) – JrmDel Oct 25 '22 at 08:35
4

Strict Comparisons

To do simple comparison, use === to check for strict equality. As others stated, this has the advantages of being most efficient and reducing the chances of buggy or uncertain code. Source: MDN Web Docs: Strict Equality.

var a = "hello1";
var b = "hello2";
console.log("a === a?" + (a === a) + "|");
console.log("a === b?" + (a === b) + "|");

Alphabetical Comparisons

If you want to compare two strings to know if a string comes before or after another string, based on natural sorting, use the <, >, <=, and >= operators. Source: MDN WebDocs for <, >, <=, and >=.

    var a = "hello1";
    var b = "hello2";
    console.log("a < a?" + (a < a) + "|");
    console.log("a < b?" + (a < b) + "|");
    console.log("a > b?" + (a > b) + "|");
    console.log("b > a?" + (b > a) + "|");
HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133
2

Considering that both strings may be very large, there are 2 main approaches bitwise search and localeCompare

I recommed this function

function compareLargeStrings(a,b){
    if (a.length !== b.length) {
         return false;
    }
    return a.localeCompare(b) === 0;
}
Nagibaba
  • 4,218
  • 1
  • 35
  • 43
2

For strings, we have a supported method localCompare which is very handy in string comparison. IMO, we should just use it and doesn't need to complicate stuff.

Usage:

const a = 'Hello'
const b = 'Hell'

a.localCompare(a) // 0
a.localCompare(b) // 1
b.localCompare(a) // -1
Hanan Mehmood
  • 295
  • 2
  • 4
  • One of the annoying things about localeCompare is that if two strings are the same, it returns a 0, meaning your code then becomes full of things like "if (!stringA.localeCompare(stringB)) ". All those not signs are ugly and, if you're not familiar with localeCompare, can make you think you're looking for a false result in the if statement instead of the true result. – Onychomys Dec 27 '22 at 15:43
  • @Onychomys I consider best to write those tests more explicitly: `if (stringA.localeCompare(stringB) === 0)`. What other result than `0` would you consider not annoying? Some constant such that the check would be something like `if (stringA.localeCompare(stringB) === ComparisonResult.orderedSame)`? – Philippe-André Lorin Jan 24 '23 at 09:48