Pytanie Który operator (== vs ===) powinien być użyty w porównaniach JavaScript?


używam JSLint przejść przez JavaScript i zwraca wiele sugestii do zamiany == (dwa równe znaki) z === (trzy znaki równości) podczas robienia rzeczy takich jak porównywanie idSele_UNVEHtype.value.length == 0 wewnątrz if komunikat.

Czy wymiana jest korzystna dla wydajności == z ===?

Każda poprawa wydajności byłaby mile widziana, ponieważ istnieje wiele podmiotów porównujących.

Jeśli nie nastąpi konwersja typu, wystąpiłby wzrost wydajności ==?


5674
2017-12-11 14:19


pochodzenie


Do kogo może być zainteresowany tym samym tematem === vs ==, ale w PHP, można przeczytać tutaj: stackoverflow.com/questions/2401478/why-is-faster-than-in-php/... - Marco Demaio
Na wypadek gdyby ktoś zastanawiał się w 2012 roku: === jest droga szybszy niż ==. jsperf.com/comparison-of-comparisons - Ry-♦
@minitech powinno być tak, jak nie robi konwersji typu - Umur Kontacı
@minitech, wątpię, czy ktokolwiek zrobi znacznie szybciej swoją aplikację === koniec ==. W rzeczywistości test porównawczy nie wykazuje dużej różnicy między obydwoma nowoczesnymi przeglądarkami. Osobiście zwykle używam == wszędzie, chyba że naprawdę potrzebuję ścisłej równości. - this.lau_
@johndodo: Przedwczesna optymalizacja to tylko rzecz, ponieważ zoptymalizowany kod może być mniej idealny z punktu widzenia łatwości konserwacji i czytelności, ale jeśli cechy konwersji typu == nie są potrzebne, korzystanie z === zamiast tego jest dobrą praktyką, a nie przedwczesną optymalizacją. Nie ma nic w tym === które pogarszają konserwowalność kodu lub jego czytelność. - Robert Harvey♦


Odpowiedzi:


Tożsamość (===) operator zachowuje się identycznie jak równość (==), z wyjątkiem braku konwersji typu, a typy muszą być takie same, aby można je było uznać za równe.

Odniesienie: Podręcznik JavaScript: Operatory porównania

The == operator porówna dla równości po wykonaniu niezbędnych konwersji typów. The === operator będzie nie wykonaj konwersję, więc jeśli dwie wartości nie są tego samego typu === po prostu wróci false. Oba są równie szybkie.

Cytując znakomity Douglas Crockford JavaScript: dobre części,

JavaScript ma dwa zestawy operatorów równości: === i !==i ich złymi bliźniakami == i !=. Te dobre działają tak, jak można by oczekiwać. Jeśli oba operandy są tego samego typu i mają tę samą wartość, to === produkuje true i !== produkuje false. Złe bliźnięta robią to, co należy, gdy operandy są tego samego typu, ale jeśli są różnych typów, próbują wymusić wartości. zasady, według których to robią, są skomplikowane i niezapomniane. Oto niektóre z interesujących przypadków:

'' == '0'           // false
0 == ''             // true
0 == '0'            // true

false == 'false'    // false
false == '0'        // true

false == undefined  // false
false == null       // false
null == undefined   // true

' \t\r\n ' == 0     // true

Brak przechodniów jest alarmujący. Moja rada jest taka, aby nigdy nie używać złych bliźniaków. Zamiast tego zawsze używaj === i !==. Wszystkie przedstawione porównania pokazują false z === operator.


Aktualizacja:

Dobra uwaga została poruszona przez @Casebash w komentarzach i w @Phillipe Laybaert's  odpowiedź dotyczące rodzajów referencji. Dla typów referencyjnych == i === działać konsekwentnie ze sobą (z wyjątkiem specjalnego przypadku).

var a = [1,2,3];
var b = [1,2,3];

var c = { x: 1, y: 2 };
var d = { x: 1, y: 2 };

var e = "text";
var f = "te" + "xt";

a == b            // false
a === b           // false

c == d            // false
c === d           // false

e == f            // true
e === f           // true

Szczególny przypadek polega na porównaniu literału z obiektem, który ocenia ten sam literał, z powodu jego wartości toString lub valueOf metoda. Rozważmy na przykład porównanie literału łańcuchowego z obiektem napisanym przez String konstruktor.

"abc" == new String("abc")    // true
"abc" === new String("abc")   // false

Tutaj == operator sprawdza wartości dwóch obiektów i zwraca true, ale === widzi, że nie są tego samego typu i powracają false. Który jest prawidłowy? To naprawdę zależy od tego, co próbujesz porównać. Moją radą jest całkowite ominięcie pytania i po prostu nie używać tego String konstruktor do tworzenia obiektów ciągów.

Odniesienie
http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3


5728
2017-12-11 14:25



=== nie jest szybszy, jeśli typy są takie same. Jeśli typy nie są takie same, === będzie szybsze, ponieważ nie będzie próbował dokonać konwersji. - Bill the Lizard
=== nigdy nie będzie wolniejsze niż ==. Oboje sprawdzają typ, więc === nie robi nic więcej w porównaniu do ==, ale kontrola typów może pozwolić na === wcześniejsze wyjście, gdy typy nie są takie same. - Bill the Lizard
Zastąpienie wszystkich == /! = Z === /! == zwiększa rozmiar pliku js, ładowanie zajmie więcej czasu. :) - Marco Demaio
"... zasady, według których to robią są skomplikowane i niezapomniane ..." Teraz takie stwierdzenia sprawiają, że czujesz się tak bezpiecznie podczas programowania ... - Johan
Czasami system typu JavaScript sprawia, że ​​chcę uciec z krzykiem. - Yawar


Używając ==operator (Równość)

true == 1; //true, because 'true' is converted to 1 and then compared
"2" == 2;  //true, because "2" is converted to 2 and then compared

Używając ===operator (Tożsamość)

true === 1; //false
"2" === 2;  //false

To dlatego, że operator równości == stosuje przymus, co oznacza, że ​​interpreter domyślnie próbuje przekonwertować wartości przed porównaniem.

Z drugiej strony operator tożsamości === nie stosuje przymusu, a zatem nie konwertuje wartości podczas porównywania.


990
2018-06-05 19:11



@Software Monkey: nie dla typów wartości (liczba, boolean, ...) - Philippe Leybaert
type coercion vs type casting vs type convertion: stackoverflow.com/questions/8857763/... - Adrien Be
Ponieważ nikt nie wspomniał o tabeli równości JavaScript, oto: dorey.github.io/JavaScript-Equality-Table - blaze
Czy w pierwszym stwierdzeniu masz pewność, że "true" jest konwertowane na 1, a nie 1 na true? - Shadi Namrouti
Skąd pochodzą pojęcia "równość" i "tożsamość"? Standard nie stosuje tych terminów. To wywołuje == "abstrakcyjna równość" i to wywołuje === "ścisła równość". Przyznane połączenia == jakakolwiek "równość" jest IMHO okropna, ponieważ nie jest przechodnia, ale dlaczego spierać się? Zaczynam jednak bardziej problem z "tożsamością"; Myślę, że ten termin jest dość mylący, chociaż "działa". Ale poważnie, kto ukuł termin "tożsamość"? Przeszukuję standard i nie mogę go znaleźć. - Ray Toal


W odpowiedziach tutaj nie czytałem niczego o czym równy znaczy. Niektórzy to powiedzą === znaczy równy i tego samego typu, ale to nie jest prawda. To w rzeczywistości oznacza to oba operandy odnoszą się do tego samego obiektulub w przypadku typy wartości mają tę samą wartość.

Więc, weźmy następujący kod:

var a = [1,2,3];
var b = [1,2,3];
var c = a;

var ab_eq = (a === b); // false (even though a and b are the same type)
var ac_eq = (a === c); // true

Tak samo tutaj:

var a = { x: 1, y: 2 };
var b = { x: 1, y: 2 };
var c = a;

var ab_eq = (a === b); // false (even though a and b are the same type)
var ac_eq = (a === c); // true

Lub nawet:

var a = { };
var b = { };
var c = a;

var ab_eq = (a === b); // false (even though a and b are the same type)
var ac_eq = (a === c); // true

Takie zachowanie nie zawsze jest oczywiste. W tej historii jest więcej niż bycie równym i bycie tego samego typu.

Zasada brzmi:

Dla typów wartości (liczby):
a === b zwraca true, jeśli a i b mają tę samą wartość i są tego samego typu

Dla typów odniesienia:
a === b zwraca true, jeśli a i b podaj dokładnie ten sam obiekt

W przypadku ciągów:
a === b zwraca true, jeśli a i b są oba ciągi i zawierają dokładnie te same znaki


Ciągi: specjalny przypadek ...

Ciągi nie są typami wartości, ale w JavaScript zachowują się jak typy wartości, więc będą "równe", gdy znaki w łańcuchu będą takie same i gdy będą miały tę samą długość (jak wyjaśniono w trzeciej regule)

Teraz staje się interesująca:

var a = "12" + "3";
var b = "123";

alert(a === b); // returns true, because strings behave like value types

Ale co powiesz na to ?:

var a = new String("123");
var b = "123";

alert(a === b); // returns false !! (but they are equal and of the same type)

Myślałem, że ciągi zachowują się jak typy wartości? Cóż, to zależy, kogo zapytasz ... W tym przypadku aib nie są tego samego typu. a jest typu Object, podczas b jest typu string. Wystarczy pamiętać, że tworzenie obiektu ciągu za pomocą String konstruktor tworzy coś w rodzaju Object który zachowuje się jak ciąg znaków większość czasu.


546
2018-05-05 05:21



activa: Chciałbym wyjaśnić, że łańcuchy są tak równe tylko wtedy, gdy są literałami. new String ("abc") === "abc" jest fałszywe (według moich badań). - Lawrence Dol
new Number() == "0". Również w Firefoksie: (function(){}) == "function () {\n}" - Thomas Eding
Dziękuję za wyjaśnienie, dlaczego new String("123") !== "123". Są to różne typy. Proste, ale mylące. - styfle
String obiekty zachowują się tak jak łańcuchy każdy inny obiekt. new String nigdy nie powinno być używane, ponieważ nie tworzy prawdziwych łańcuchów. Prawdziwy ciąg znaków i można go utworzyć za pomocą literałów lub wywoływania ciągów znaków String jako funkcja bez  new, na przykład: String(0); //"0", Real string, not an object - Esailija
Ale w przypadkach, które szczegółowo opisano, operator "==" zachowuje się dokładnie tak samo. - Yaron Levi


Ciekawa obrazkowa reprezentacja porównania równości między == i ===.

Źródło: http://dorey.github.io/JavaScript-Equality-Table/


var1 === var2

Podczas używania === do testowania równości w JavaScript wszystko jest jak jest. Nic nie zostanie przekształcone przed oceną.

Equality evaluation of === in JS


var1 == var2

Podczas używania == do testowania równości JavaScript, niektóre   zaczynają się funky konwersje.

Equality evaluation of == in JS

Morał historii: 

Posługiwać się === chyba że w pełni zrozumiesz   konwersje, które mają miejsce ==.


522
2017-11-28 18:18



@mfeineis masz na myśli === lub! == zamiast == lub! =. Nie chcę mylić nowych programistów;) - katalin_2003
@ katalin_2003 oops, masz rację === i! ==, d ** n literówek, thx - mfeineis
@vsync: Wow, ci, którzy nadużywają JQuery, również mówią to samo. Nigdy nie wiedziałem, że masz ze sobą tyle wspólnego ...
@vsync: Jeśli naprawdę nie chcę, aby typy były równe, ty powinien posługiwać się trzy równe! - SNag
Ta odpowiedź jest cholernie przydatna !!! - skiabox


Pozwól mi dodać tę radę:

W razie wątpliwości przeczytaj specyfikacja! 

ECMA-262 jest specyfikacją języka skryptowego, którego JavaScript jest dialektem. Oczywiście w praktyce ważniejsze jest to, jak zachowują się najważniejsze przeglądarki, niż ezoteryczna definicja tego, jak coś ma być obsługiwane. Ale pomocne jest zrozumienie, dlaczego nowy ciąg ("a")! == "a".

Proszę pozwolić mi wyjaśnić, jak przeczytać specyfikację, aby wyjaśnić to pytanie. Widzę, że w tym bardzo starym temacie nikt nie miał odpowiedzi na bardzo dziwny efekt. Tak więc, jeśli potrafisz przeczytać specyfikację, to pomoże ci w twoim zawodzie ogromnie. Jest to nabyta umiejętność. Kontynuujmy.

Wyszukiwanie pliku PDF dla === prowadzi mnie do strony 56 specyfikacji: 11.9.4. The Strict Equals Operator (===), a po przejściu przez specyfikację znajduję:

11.9.6 Algorytm ścisłego porównywania równości
  Porównanie x === y, gdzie xiy są wartościami, produkuje prawdziwe lub fałszywy. Takie porównanie przeprowadza się w następujący sposób:
  1. Jeśli Typ (x) różni się od Typ (y), powróć fałszywy.
  2. Jeśli Typ (x) jest niezdefiniowany, wróć prawdziwe.
  3. Jeśli Type (x) ma wartość Null, return prawdziwe.
  4. Jeśli Typ (x) nie jest liczbą, przejdź do kroku 11.
  5. Jeśli x jest NaN, powrót fałszywy.
  6. Jeśli y jest NaN, powrót fałszywy.
  7. Jeśli x ma tę samą wartość liczbową co y, powróć prawdziwe.
  8. Jeśli x to +0, a y oznacza -0, to powróć prawdziwe.
  9. Jeśli x to -0, a y jest +0, to wróć prawdziwe.
  10. Powrót fałszywy.
  11. Jeśli Type (x) jest String, a następnie wróć prawdziwe jeśli x i y to dokładnie ta sama sekwencja znaków (ta sama długość i te same znaki w odpowiednich pozycjach); inaczej, wróć fałszywy.
  12. Jeśli Typ (x) jest wartością logiczną, zwróć prawdziwe jeśli x i y są oba prawdziwe lub oba fałszywy; inaczej, wróć fałszywy.
  13. Powrót prawdziwe jeśli x i y odnoszą się do tego samego obiektu lub odnoszą się do obiektów połączonych ze sobą (patrz 13.1.2). W przeciwnym razie zwróć fałszywy.

Interesujący jest krok 11. Tak, ciągi są traktowane jako typy wartości. Ale to nie wyjaśnia, dlaczego nowy ciąg ("a")! == "a". Czy mamy przeglądarkę niezgodną z ECMA-262?

Nie tak szybko!

Sprawdźmy typy operandów. Wypróbuj sam, owijając je typ(). Znajduję to nowy ciąg ("a") jest obiektem, a krok 1 jest używany: return fałszywy jeśli typy są różne.

Jeśli zastanawiasz się, dlaczego nowy ciąg ("a") nie zwraca łańcucha, a może trochę ćwiczeń czytających specyfikację? Baw się dobrze!


Aidiakapi napisał to w komentarzu poniżej:

Ze specyfikacji

11.2.2 Nowy operator:

Jeśli Typ (konstruktor) nie jest obiektem, należy rzucić wyjątek TypeError.

Innymi słowy, jeśli String nie byłby obiektem typu, nie można go użyć z nowym operatorem.

Nowy zawsze zwraca obiekt, nawet dla Strunowy także konstruktorzy. I niestety! Wartość semantyki dla ciągów (patrz krok 11) zostanie utracona.

A to w końcu oznacza: nowy ciąg ("a")! == "a".


250
2018-05-12 12:58



Wynik typu (x) jest domyślnie taki sam jak typof? - Dfr


W PHP i JavaScript jest to operator ścisłej równości. Co oznacza, że ​​porównuje zarówno typ, jak i wartości.


93
2017-12-25 11:17



@David: poprawny. Dlatego ta odpowiedź jest niedokładna (lub nawet błędna) - Philippe Leybaert
@ David var a = {}, b = {};  a == b zwraca false. - nyuszika7h
Tak: dwa różne obiekty o tym samym typie i wartości porównują fałsz, tj. ta odpowiedź jest po prostu błędna. Dlaczego ma 50 przegranych? - alexis
Rozumiem, że to jest stare, ale wyjaśnienie, dlaczego ta odpowiedź jest nadal "poprawna", jest takie, jak w przykładzie var a = {}, b = {}; Podczas gdy jedno i drugie a i b jest rzeczywiście zarówno przedmiotem, ale nie są podobnie wartość, technicznie rzecz biorąc. Oni są różne instancje. Należy zauważyć, że porównywanie instancji zachowuje się inaczej niż porównywanie prymitywów. Co prawdopodobnie przyczynia się do tego zamieszania. Podobne zachowanie porównawcze będzie widoczne, jeśli użyjesz podstawowej wersji pierwotnych typów danych. Na przykład new String('asdf') lub new Number(5). Dawny: new Number(5) == new Number(5) jest fałszywa, mimo że mają tę samą wartość. - Norman Breau


Testowałem to w Firefoksie z Firebug używając takiego kodu:

console.time("testEquality");
var n = 0;
while(true) {
    n++;
    if(n==100000) 
        break;
}
console.timeEnd("testEquality");

i

console.time("testTypeEquality");
var n = 0;
while(true) {
    n++;
    if(n===100000) 
        break;
}
console.timeEnd("testTypeEquality");

Moje wyniki (testowane pięć razy i uśrednione):

==: 115.2
===: 114.4

Powiedziałbym więc, że niewielka różnica (jest to ponad 100 000 iteracji, pamiętaj) jest znikoma. Wydajność nie jest powód do zrobienia ===. Wpisz bezpieczeństwo (dobrze, tak bezpiecznie, jak chcesz uzyskać JavaScript), a jakość kodu jest.


88
2018-05-12 12:58



Więcej niż bezpieczeństwo typu, które chcesz poprawić logicznie - czasami chcesz, aby rzeczy były prawdziwe, kiedy == nie zgadza się. - rpjohnst
Teraz, jak te porównania, gdy istnieje rzeczywisty typ dla == operator? Pamiętaj, że wtedy następuje wzrost wydajności. - Hubert OG
MAJORA Różnica, gdy testowane prawidłowo z wyżej wymienionych powodów szybszego do sprawdzenia tylko nierówności typu. jsfiddle.net/4jhuxkb2 - Doug Morrow


W JavaScript oznacza to tę samą wartość i typ.

Na przykład,

4 == "4" // will return true

ale

4 === "4" // will return false 

84
2017-12-11 14:58





The === operator nazywa się ścisłym operatorem porównania, to robi różnią się od == operator.

Pozwala wziąć 2 vary aib.

Dla "a == b" ocenić jako prawdziwe aib musieć ta sama wartość.

W przypadku "a === b" aib muszą być ta sama wartość a także taki sam typ aby to ocenić na prawdę.

Weź następujący przykład

var a = 1;
var b = "1";

if (a == b) //evaluates to true as a and b are both 1
{
    alert("a == b");
}

if (a === b) //evaluates to false as a is not the same type as b
{
    alert("a === b");
}

W podsumowaniu; używając == operator może ocenić wartość true w sytuacjach, w których nie chcesz tego używać === operator byłby bezpieczniejszy.

W scenariuszu 90% użycia nie ma znaczenia, którego z nich używasz, ale dobrze jest wiedzieć, kiedy pewnego dnia wystąpią nieoczekiwane zachowania.


73
2018-05-12 12:58



Oto szczegółowy artykuł na temat porównania === vs == - Zaheer Ahmed


Sprawdza, czy te same boki są równe rodzaj jak również wartość.

Przykład:

'1' === 1 // will return "false" because `string` is not a `number`

Typowy przykład:

0 == ''  // will be "true", but it's very common to want this check to be "false"

Inny typowy przykład:

null == undefined // returns "true", but in most cases a distinction is necessary

64
2017-09-05 13:53



również, 'string' !== 'number' - Homer