Jaki jest prawidłowy sposób sprawdzania równości ciągów w JavaScript?


842

Jaki jest prawidłowy sposób sprawdzenia równości między ciągami w JavaScript?


2
Czy istnieje powód, aby nie używać ==?
Kendrick

21
@Kendrick - jasne. Jest to system przymusu typu, który może być niezwykle nieintuicyjny i może bardzo łatwo przeoczyć błędy ( wygląda dobrze, ale może być bardzo błędny)
STW

20
@Kendrick - ponieważ {} == "[object Object]"na przykład ma wartość true.
Chetan Sastry

12
nieco denerwujące, że String().equals()nie jest to metoda w JS ...
Alexander Mills

2
@AlexanderMills Dlaczego?
Ry-

Odpowiedzi:


624

zawsze Dopóki nie w pełni zrozumiesz różnice i implikacje korzystania zoperatorów==i===, użyj===operatora, ponieważ uratuje cię to od niejasnych (nieoczywistych) błędów i WTF. „Zwykły”==operator może mieć bardzo nieoczekiwane wyniki ze względu na wewnętrzny przymus typu, więc użycie===jest zawsze zalecanym podejściem.

Aby uzyskać wgląd w to i inne „dobre kontra złe” części Javascript, poczytałem o Douglasie Crockfordie i jego pracy. Jest świetna Google Tech Talk, w której podsumowuje wiele dobrych informacji: http://www.youtube.com/watch?v=hQVTIJBZook


Aktualizacja:

Seria You Don't Know JS autorstwa Kyle'a Simpsona jest doskonała (i do przeczytania online za darmo). Seria omawia często źle rozumiane obszary języka i wyjaśnia „złe strony”, których sugeruje Crockford. Rozumiejąc je, możesz właściwie z nich korzystać i unikać pułapek.

Książka „ Up & Going ” zawiera sekcję dotyczącą równości , z tym konkretnym podsumowaniem, kiedy należy używać operatorów loose ( ==) vs strict ( ===):

Aby sprowadzić wiele szczegółów do kilku prostych dań na wynos i pomóc ci wiedzieć, czy użyć, ==czy ===w różnych sytuacjach, oto moje proste zasady:

  • Jeśli którakolwiek wartość (inaczej strona) w porównaniu może być wartością truelub false, należy unikać ==i używać ===.
  • Jeśli wartość w porównaniu z nich może być konkretne wartości ( 0, ""lub []- pusta tablica), należy unikać ==i zastosowania ===.
  • We wszystkich innych przypadkach możesz bezpiecznie używać ==. Jest nie tylko bezpieczny, ale w wielu przypadkach upraszcza kod w sposób poprawiający czytelność.

Nadal polecam przemówienie Crockforda programistom, którzy nie chcą poświęcać czasu na prawdziwe zrozumienie Javascript - to dobra rada dla programistów, którzy tylko czasami pracują w Javascript.


7
Nie jest to konieczne, gdy masz pewność, że oba operandy są ciągami znaków, np. Podczas używaniaif (typeof foo == "string")
Marcel Korpel

25
@Marcel - masz rację, ale o wiele lepiej jest zawsze używać ===operatora i nigdy nie martwić się o to, czy „naprawdę jestem w 100% pewien, że ==zachowam się tak, jak myślę?”
STW

7
@STW - jednym z przykładów, dlaczego Crockford nie jest alfą i omegą JavaScript, jest jego rada, aby nie używać jednostkowego przyrostu / zmniejszenia ( ++/ --).
Marcel Korpel

10
I nigdy nie używaj ++ani oświadczeń --jednowierszowych, ani operatora, ani żadnej innej całkowicie uzasadnionej praktyki kodowania, którą Crockford uznał za „szkodliwą”. I oczywiście nigdy nawet nie zastanawia się nad użyciem, a nawet jeśli ich pułapki są dobrze zrozumiane. I widziałeś kolejną wersję JS? Bardziej rygorystyczna składnia i kilka funkcji pomocniczych, z których niektóre latają od lat, to wszystko, co otrzymujemy po całym tym czasie. Składnia wcale się nie zmieniła. Jeśli za tym stoi Crockford, to było źle. if/elsecontinuenewevalwith
MooGoo,

4
@CoffeeAddict - szybki test w JSFiddle wydaje się nie zgadzać. W obu przypadkach rozróżniana jest wielkość liter
STW

204

Jeśli wiesz, że są łańcuchami, nie ma potrzeby sprawdzania typu.

"a" == "b"

Należy jednak pamiętać, że obiekty łańcuchowe nie będą równe.

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

zwróci fałsz.

Wywołaj metodę valueOf (), aby przekształcić ją w operację podstawową dla obiektów String,

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

zwróci prawdę


4
dzięki za ten JSS dwa obiekty łańcuchowe nigdy nie będą równe, chyba że będą tym samym obiektem niezależnie od wartości.
Anurag

4
@JSS: Dodatkowo new String("a") == "a"jest prawdą (ale nie byłoby ===), ponieważ lewa strona zostanie przekonwertowana na pierwotną wartość ciągu.
Matthew Crumley

5
@JSS: new String("a") == new String("a"), new String("a") === new String("b"), new String("a") === new String("a")będzie cały zwrot false, ponieważ masz do czynienia z odniesieniami do obiektów w Stringklasie, a nie prymitywów typu string.
palswim

4
Aby wyjaśnić to każdemu, kto to czyta. new String(foo)tworzy obiekt łańcuchowy i String(foo) konwertuje foo na łańcuch podstawowy.
Brigand

9
@FakeRainBrigand - jasne jak błoto, ale o to chodzi w skryptach javascript, prawda?
Periata Breatta

58

Tylko jeden dodatek do odpowiedzi: Jeśli wszystkie te metody zwracają wartość false, nawet jeśli łańcuchy wydają się być równe, możliwe jest, że po lewej i / lub prawej stronie jednego łańcucha występuje spacja. Więc po prostu umieść .trim()na końcu łańcucha przed porównaniem:

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

Straciłem godziny, próbując dowiedzieć się, co jest nie tak. Mam nadzieję, że to komuś pomoże!


1
Wielkie dzięki. Jest to dla mnie dziwne, ponieważ upewniłem się, że nie ma białych znaków po lewej ani po prawej stronie i wciąż był to jedyny sposób rozwiązania mojego problemu. Może ma to związek z wewnętrzną reprezentacją łańcucha?
Niko

2
Dzięki @akelec !! @Niko, prawdopodobnie wynikało to z postaci Zero-Szerokość-Przestrzeń, która jest niewidoczna gołym okiem. Zobacz en.wikipedia.org/wiki/Zero-width_space . Mimo że ta postać ma swoje cele, wielu deweloperów jest oburzonych jej istnieniem!
stwr667

Dziękuję, że było to frustrujące, ponieważ sprawdzanie równości w moim przypadku nie powiodło się, ale nie widziałem spacji podczas inspekcji podczas debugowania.
drzounds

Typowy problem podczas ładowania zmiennej z pliku tekstowego (np. Przy użyciu fetch). Wielkie dzięki.
Sopalajo de Arrierez

@SopalajodeArrierez, dokładnie, na końcu łańcucha występuje spacja lub znak powrotu karetki. Zapraszamy.
akelec

22

to, co doprowadziło mnie do tego pytania, to paddingiwhite-spaces

sprawdź moją sprawę

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

i tytuł był " LastName"

wprowadź opis zdjęcia tutaj

więc może musisz użyć trimtakiej funkcji

var title = $(this).text().trim();

2
Dzięki to samo tutaj użyłem .toString().trim()w
maszynopisie

17

O ile naprawdę nie wiesz, jak działa przymus, powinieneś unikać ==operatora tożsamości i używać go ===. Ale powinieneś przeczytać to, aby zrozumieć, jak to działa .

Jeśli używasz ==, pozwalasz językowi na wykonanie pewnego przymusu, więc na przykład:

"1" == 1 // true
"0" == false // true
[] == false // true

Jak powiedział Douglas Crockford w swojej książce:

Zawsze lepiej jest użyć operatora tożsamości.


3
Chociaż ten link może odpowiedzieć na pytanie, lepiej dołączyć tutaj istotne części odpowiedzi i podać link w celach informacyjnych. Odpowiedzi zawierające tylko łącze mogą stać się nieprawidłowe, jeśli połączona strona ulegnie zmianie.
Parkash Kumar

{}==" "dał mi Unexpected token ==właściwy sposób, aby to zrobić?
Basheer AL-MOMANI,

12

Istnieją dwa sposoby tworzenia łańcuchów w javascript.

  1. var str = 'Javascript'; To tworzy prymitywną wartość ciągu.

  2. var obj = new String('Javascript');Spowoduje to utworzenie typu opakowania String.

    typeof str // string
    typeof obj // object

Zatem najlepszym sposobem sprawdzenia równości jest użycie ===operatora, ponieważ sprawdza on wartość, a także rodzaj obu operandów.

Jeśli chcesz sprawdzić równość między dwoma obiektami, użyj String.prototype.valueOfpoprawnego sposobu.

new String('javascript').valueOf() == new String('javascript').valueOf()

6

Ciąg Objectsmożna sprawdzić za pomocą JSON.stringyfy()sztuczki.

var me = new String("me");
var you = new String("me");
var isEquel = JSON.stringify(me) === JSON.stringify(you);
console.log(isEquel);


1

Biorąc pod uwagę, że oba ciągi mogą być bardzo duże, istnieją 2 główne podejścia bitwise searchilocaleCompare

Poleciłem tę funkcję

function compareLargeStrings(a,b){
    if (a.length !== b.length) {
         return false;
    }
    return a.localeCompare(b) === 0;
}

-2

Najłatwiej to zrobić, używając operatora trójskładnikowego:

 "was" == "was" ? true : false

ale jeśli ciąg, który chcesz porównać, znajduje się w tablicy, użyjesz filtru es6

let stringArray  = ["men", "boys", "girls", "sit", "can", "gotten"]
stringArray.filter(I=> I === boys ? 
stringArray.pop(indexOf(I)) : null)

powyższe sprawdzi twój stringArray i dowolny ciąg pasujący do niego z tablicy, która w naszym przypadku wybraliśmy „boys”


-8

Podczas testów wymyśliłem alternatywne rozwiązanie. możesz użyć funkcji na prototypie łańcucha.

String.prototype.betwenStr = function(one){

return JSON.stringify(new String(this)) === JSON.stringify(new String(one));

}


 //call it
 "hello world".betweenStr("hello world"); //returns boolean 
 //value

działa dobrze w przeglądarkach Chrome


Pytanie dotyczy tego, jak sprawdzić, czy „hello world” = „hello world”, a nie, jak sprawdzić, czy „hello world” jest ciągiem znaków.
Nick

4
To jest po prostu głupie. Utworzyłeś wersję Rube Goldberg ==.
JJJ,

Cześć OP, twoja edycja jest zupełnie inna pod względem duchowym, a twoja odpowiedź ma już zbyt wiele głosów negatywnych. Zachęcam do usunięcia tej odpowiedzi i opublikowania nowej w edytowanej wersji
Yılmaz Durmaz
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.