Welcher Gleichheitsoperator (== vs ===) sollte in JavaScript-Vergleichen verwendet werden?


5665

Ich verwende JSLint , um JavaScript zu durchlaufen, und es werden viele Vorschläge zurückgegeben, die ersetzt werden sollen ==(zwei Gleichheitszeichen) durch ===(drei Gleichheitszeichen), wenn beispielsweise Dinge idSele_UNVEHtype.value.length == 0innerhalb einer ifAnweisung verglichen werden .

Gibt es einen Leistungsvorteil beim Ersetzen ==durch ===?

Jede Leistungsverbesserung wäre zu begrüßen, da viele Vergleichsoperatoren existieren.

Wenn keine Typkonvertierung stattfindet, würde sich dann ein Leistungsgewinn ergeben ==?


134
Für wen es sich für das gleiche Thema interessieren könnte === vs ==, aber für PHP, kann hier gelesen werden: stackoverflow.com/questions/2401478/why-is-faster-than-in-php/…
Marco Demaio

257
Nur für den Fall, dass sich 2012 jemand wunderte: ===ist viel schneller als ==. jsperf.com/comparison-of-comparisons
Ry-

25
@minitech sollte es sein, da es keine Typkonvertierung macht
Umur Kontacı

19
@minitech, ich bezweifle, dass jemand seine Anwendung durch die Verwendung von ===over spürbar schneller machen wird ==. Tatsächlich zeigt der Benchmark bei modernen Browsern keinen großen Unterschied zwischen beiden. Persönlich benutze ich normalerweise ==überall, es sei denn, ich brauche wirklich strenge Gleichheit.
Laurent

5
Hier ist der Teil von Crockfords JS The Good Parts- Vortrag, in dem er die ===und die ==Betreiber bespricht : youtube.com/… Wenn es nicht
abgespielt wird

Antworten:


6485

Der strikte Gleichheitsoperator ( ===) verhält sich identisch mit dem abstrakten Gleichheitsoperator ( ==), außer dass keine Typkonvertierung durchgeführt wird und die Typen identisch sein müssen, um als gleich zu gelten.

Referenz: Javascript Tutorial: Vergleichsoperatoren

Der ==Operator vergleicht die Gleichheit, nachdem er alle erforderlichen Typkonvertierungen durchgeführt hat . Der ===Bediener wird nicht die Konvertierung tun, so dass , wenn zwei Werte sind nicht vom gleichen Typ ===einfach zurück false. Beide sind gleich schnell.

Um Douglas Crockfords exzellentes JavaScript zu zitieren : The Good Parts ,

JavaScript hat zwei Sätze von Gleichheitsoperatoren: ===und !==, und ihre bösen Zwillinge ==und !=. Die Guten arbeiten so, wie Sie es erwarten würden. Wenn die beiden Operanden vom gleichen Typ sind und den gleichen Wert haben, wird ===erzeugt trueund !==erzeugt false. Die bösen Zwillinge tun das Richtige, wenn die Operanden vom gleichen Typ sind, aber wenn sie vom unterschiedlichen Typ sind, versuchen sie, die Werte zu erzwingen. Die Regeln, nach denen sie das tun, sind kompliziert und unvergesslich. Dies sind einige der interessanten Fälle:

'' == '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

Gleichheitsvergleichstabelle

Der Mangel an Transitivität ist alarmierend. Mein Rat ist, niemals die bösen Zwillinge zu benutzen. Verwenden Sie stattdessen immer ===und !==. Alle soeben gezeigten Vergleiche ergeben sich falsemit dem ===Bediener.


Aktualisieren:

Ein guter Punkt wurde von @Casebash in den Kommentaren und in der Antwort von @Phillipe Laybaert zu Objekten angesprochen . Für Objekte ==und ===konsequent miteinander handeln (außer in einem besonderen Fall).

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

Der Sonderfall ist, wenn Sie ein Grundelement mit einem Objekt vergleichen, das aufgrund seiner Methode toStringoder derselben valueOfMethode als dasselbe Grundelement ausgewertet wird. Betrachten Sie beispielsweise den Vergleich eines Zeichenfolgenprimitivs mit einem Zeichenfolgenobjekt, das mit dem StringKonstruktor erstellt wurde.

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

Hier ==überprüft der Operator die Werte der beiden Objekte und gibt sie zurück true, ===sieht jedoch, dass sie nicht vom gleichen Typ sind und zurückkehren false. Welches ist richtig? Das hängt wirklich davon ab, was Sie vergleichen möchten. Mein Rat ist, die Frage vollständig zu umgehen und den StringKonstruktor nicht zum Erstellen von Zeichenfolgenobjekten aus Zeichenfolgenliteralen zu verwenden.

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


236
=== ist nicht schneller, wenn die Typen gleich sind. Wenn die Typen nicht identisch sind, ist === schneller, da nicht versucht wird, die Konvertierung durchzuführen.
Bill the Lizard

520
=== wird niemals langsamer als == sein. Beide führen eine Typprüfung durch, sodass === im Vergleich zu == nichts extra tut, aber die Typprüfung kann es ermöglichen, dass === früher beendet wird, wenn die Typen nicht gleich sind.
Bill the Lizard

246
Das Ersetzen aller == /! = Durch === /! == erhöht die Größe der js-Datei. Das Laden dauert dann länger. :)
Marco Demaio

92
"... die Regeln, nach denen sie das tun, sind kompliziert und unvergesslich ..." Mit solchen Aussagen fühlen Sie sich beim Programmieren so sicher ...
Johan

47
Von Crockford: "Der Mangel an Transitivität ist alarmierend." Wenn Sie Software entwickeln und einen Mangel an Transitivität in einem Vergleichsoperator nicht als alarmierend empfinden oder wenn der Geschwindigkeitsvergleich zwischen == und === oder die Dateigröße / Ladezeit in Ihrem Kopf Vorrang vor dem transitiven Determinismus des Verhaltens eines Vergleichsoperators haben, sind Sie Möglicherweise müssen Sie zurückgehen und von vorne beginnen.
Jinglesthula

1144

Verwenden des ==Operators ( Gleichheit )

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

Verwendung der === Operators ( Identität )

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

Das liegt daran, dass die Gleichheitsoperator ==Zwang eingibt , was bedeutet, dass der Interpreter implizit versucht, die Werte vor dem Vergleich zu konvertieren.

Auf der anderen Seite führt der Identitätsoperator ===keinen Typzwang durch und konvertiert daher die Werte beim Vergleich nicht und ist daher schneller (gemäß diesem JS-Benchmark- Test), wenn er einen Schritt überspringt.


9
@ Software Monkey: nicht für Werttypen (Zahl, Boolescher Wert, ...)
Philippe Leybaert

34
Da niemand die Javascript Equality Table erwähnt hat, ist hier: dorey.github.io/JavaScript-Equality-Table
Blaze

6
Sind Sie in der ersten Aussage sicher, dass 'true' in 1 und nicht 1 in true konvertiert wird?
Shadi Namrouti

2
Woher kommen die Begriffe "Gleichheit" und "Identität"? Der Standard verwendet diese Begriffe nicht. Es nennt =="abstrakte Gleichheit" und es nennt ==="strenge Gleichheit". Zugegeben, ==jede Art von "Gleichheit" zu nennen, ist meiner Meinung nach schrecklich, da es nicht transitiv ist, aber warum streiten? Ich habe jedoch mehr Probleme mit "Identität"; Ich denke, dieser Begriff ist ziemlich irreführend, obwohl er "funktioniert". Aber im Ernst, wer hat den Begriff "Identität" geprägt? Ich suche den Standard und konnte ihn nicht finden.
Ray Toal

1
"Identität" ist sehr viel das falsche Wort. Identitätsvergleiche in allen Sprachen , die ich verwendet habe , mittels einem in dem gleichen Objekt , dh die beiden Bezugsgrößen weisen nicht nur auf äquivalente Einheiten, aber die gleiche Einheit.
Inigo

724

Eine interessante bildliche Darstellung des Gleichheitsvergleichs zwischen ==und ===.

Quelle: http://dorey.github.io/JavaScript-Equality-Table/


var1 === var2

Bei der Verwendung ===für JavaScript-Gleichheitstests ist alles so, wie es ist. Vor der Auswertung wird nichts konvertiert.

Gleichheitsbewertung von === in JS


var1 == var2

Bei der Verwendung ==für JavaScript-Gleichheitstests finden einige funky Konvertierungen statt.

Gleichheitsbewertung von == in JS

Moral der Geschichte:

Verwenden ===Sie diese Option, es sei denn, Sie verstehen die Konvertierungen, mit denen durchgeführt wird, vollständig ==.


3
@mfeineis meinst du === oder! == statt == oder! =. Ich möchte keine neuen
Programmierer

2
Aus meiner Erfahrung kann die Verwendung von drei Gleichen Probleme verursachen und sollte vermieden werden, wenn sie nicht vollständig verstanden werden. Zwei Gleiche führen zu viel besseren Ergebnissen, da ich in 99% der Fälle wirklich nicht möchte, dass Typen gleich sind.
vsync

13
@vsync: Wenn Sie wirklich nicht wollen Typen gleich sein , Sie sollten verwenden drei Gleichen !
SNag

7
Die einzige Ausnahme: Sie können sicher verwenden x == nullzu überprüfen , ob xist nulloder undefined.
Andy

1
@ user648026: Die Frage ist über Gleichheit Vergleich mit ==vs ===. Groß- und Kleinschreibung sind ohnehin ungleich und werden falsesowohl mit als auch ==mit ===Operatoren zurückgegeben. Auch Schlüsselwörter true, false, undefined, null, Infinityexistieren in JS nur in einem Fall und können nicht in der oberen oder gemischten Fällen verwendet werden.
SNag

609

In den Antworten hier habe ich nichts darüber gelesen, was Gleichheit bedeutet. Einige werden sagen, das ===bedeutet gleich und vom gleichen Typ , aber das ist nicht wirklich wahr. Dies bedeutet tatsächlich, dass beide Operanden auf dasselbe Objekt verweisen oder bei Werttypen denselben Wert haben .

Nehmen wir also den folgenden Code:

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

Dasselbe hier:

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

Oder auch:

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

Dieses Verhalten ist nicht immer offensichtlich. Die Geschichte hat mehr zu bieten, als gleich zu sein und vom selben Typ zu sein.

Die Regel lautet:

Für Werttypen (Zahlen):
a === b Gibt true zurück, wennaundbhaben denselben Wert und sind vom gleichen Typ

Für Referenztypen:
a === b Gibt true zurück, wennaundbgenau dasselbe Objekt referenziert wird

Für Zeichenfolgen:
a === b Gibt true zurück, wennaundb beide Zeichenfolgen sind und genau dieselben Zeichen enthalten


Saiten: der Sonderfall ...

Zeichenfolgen sind keine Werttypen, aber in Javascript verhalten sie sich wie Werttypen. Sie sind also "gleich", wenn die Zeichen in der Zeichenfolge gleich und gleich lang sind (wie in der dritten Regel erläutert).

Jetzt wird es interessant:

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

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

Aber wie wäre es damit?:

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

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

Ich dachte, Strings verhalten sich wie Werttypen? Nun, es kommt darauf an, wen Sie fragen ... In diesem Fall sind a und b nicht vom gleichen Typ. aist vom Typ Object, während bvom Typ ist string. Denken Sie daran, dass beim Erstellen eines Zeichenfolgenobjekts mit dem StringKonstruktor etwas erstellt wird, Objectdas sich die meiste Zeit als Zeichenfolge verhält .


6
activa: Ich würde klarstellen, dass die Zeichenfolgen nur dann so gleich sind, wenn sie wörtlich sind. new String ("abc") === "abc" ist falsch (nach meinen Recherchen).
Lawrence Dol

3
new Number() == "0". Ebenfalls in Firefox:(function(){}) == "function () {\n}"
Thomas Eding

3
Vielen Dank für die Erklärung, warum new String("123") !== "123". Sie sind verschiedene Arten. Einfach und doch verwirrend.
Styfle

21
StringObjekte verhalten sich wie jedes andere Objekt wie Zeichenfolgen . new Stringsollte niemals verwendet werden, da dies keine echten Strings erzeugt. Eine echte Zeichenfolge und kann mit Zeichenfolgenliteralen erstellt oder Stringals Funktion newString(0); //"0", Real string, not an object
aufgerufen

6
In den von Ihnen beschriebenen Fällen verhält sich der Operator "==" jedoch genauso.
Yaron Levi

270

Lassen Sie mich diesen Rat hinzufügen:

Im Zweifelsfall die Spezifikation lesen !

ECMA-262 ist die Spezifikation für eine Skriptsprache, deren Dialekt JavaScript ist. In der Praxis ist es natürlich wichtiger, wie sich die wichtigsten Browser verhalten, als eine esoterische Definition, wie etwas gehandhabt werden soll. Es ist jedoch hilfreich zu verstehen, warum ein neuer String ("a")! == "a" .

Bitte lassen Sie mich erklären, wie die Spezifikation zu lesen ist, um diese Frage zu klären. Ich sehe, dass in diesem sehr alten Thema niemand eine Antwort auf den sehr seltsamen Effekt hatte. Wenn Sie also eine Spezifikation lesen können, hilft Ihnen dies in Ihrem Beruf enorm. Es ist eine erworbene Fähigkeit. Also, lass uns weitermachen.

Durch Durchsuchen der PDF-Datei nach === komme ich zu Seite 56 der Spezifikation: 11.9.4. Der Strict Equals Operator (===) und nach dem Durchblättern der Spezifikation finden ich:

11.9.6 Der Algorithmus für
den Vergleich strikter Gleichheit Der Vergleich x === y, wobei x und y Werte sind, ergibt wahr oder falsch . Ein solcher Vergleich wird wie folgt durchgeführt:
  1. Wenn sich Typ (x) von Typ (y) unterscheidet, geben Sie false zurück .
  2. Wenn Typ (x) undefiniert ist, geben Sie true zurück .
  3. Wenn Typ (x) Null ist, geben Sie true zurück .
  4. Wenn Typ (x) nicht Zahl ist, fahren Sie mit Schritt 11 fort.
  5. Wenn x NaN ist , geben Sie false zurück .
  6. Wenn y NaN ist , geben Sie false zurück .
  7. Wenn x der gleiche Zahlenwert wie y ist, geben Sie zurück true zurück .
  8. Wenn x +0 und y −0 ist, geben Sie true zurück .
  9. Wenn x −0 und y +0 ist, geben Sie true zurück .
  10. Geben Sie false zurück .
  11. Wenn Typ (x) String ist, geben Sie true zurück, wenn x und y genau dieselbe Zeichenfolge sind (gleiche Länge und gleiche Zeichen an den entsprechenden Positionen). Andernfalls geben Sie false zurück .
  12. Wenn Typ (x) boolesch ist, geben Sie true zurück, wenn x und y beide true oder beide false sind . Andernfalls geben Sie false zurück .
  13. Geben Sie true zurückwenn sich x und y auf dasselbe Objekt beziehen oder wenn sie sich auf miteinander verbundene Objekte beziehen (siehe 13.1.2). Andernfalls geben Sie false zurück .

Interessant ist Schritt 11. Ja, Zeichenfolgen werden als Werttypen behandelt. Dies erklärt jedoch nicht, warum ein neuer String ("a")! == "a" . Haben wir einen Browser, der nicht ECMA-262 entspricht?

Nicht so schnell!

Lassen Sie uns die Typen der Operanden überprüfen. Probieren Sie es selbst aus, indem Sie sie in typeof () einwickeln . Ich finde, dass der neue String ("a") ein Objekt ist und Schritt 1 verwendet wird: Geben Sie false zurück, wenn die Typen unterschiedlich sind.

Wenn Sie sich fragen, warum ein neuer String ("a") keinen String zurückgibt, wie wäre es dann mit einer Übung zum Lesen einer Spezifikation? Habe Spaß!


Aidiakapi schrieb dies in einem Kommentar unten:

Aus der Spezifikation

11.2.2 Der neue Operator :

Wenn Type (Konstruktor) nicht Object ist, lösen Sie eine TypeError-Ausnahme aus.

Mit anderen Worten, wenn String nicht vom Typ Object wäre, könnte er nicht mit dem neuen Operator verwendet werden.

new gibt immer ein Objekt zurück, auch für String Konstruktoren. Und leider! Die Wertesemantik für Zeichenfolgen (siehe Schritt 11) geht verloren.

Und das bedeutet schließlich: neuer String ("a")! == "a" .


Das Ergebnis von Typ (x) ist das gleiche wie das von?
Dfr

@nalply Ich verstehe die Angst vor dem Verhalten nicht genau new String('x'), weil ich noch nie einen Code in freier Wildbahn gesehen habe, der primitive Wrapper-Objekte verwendet, und ich glaube nicht, dass es dafür einen guten Grund gibt, besonders nicht heutzutage. Haben Sie jemals Code gefunden, der dies tut?
Andy

@Andy das Problem ist böswilliger oder nur schlampiger Code von Drittanbietern, dann können Sie nicht davon ausgehen, dass niemand verwendet new String().
Nalply

Wenn es schlampig ist, werden Sie es herausfinden. Wenn es bösartig ist, denke ich, new String()ist es wahrscheinlich die geringste Ihrer Sorgen. Ich verstehe die Besorgnis in der Theorie, aber haben Sie wieder Beispiele aus der Praxis? Für mich ist es wie die alte Angst, dass jemand einen undefinedanderen Wert einstellen könnte .
Andy

Ich weiß nicht, woher Sie das haben, aber Ihr Vergleichsalgorithmus wird in Schritt 2 falsch. In Abschnitt "7.2.15 Strenger Gleichheitsvergleich" wird zunächst geprüft, ob die Typen gleich sind, wenn ja, ob es sich um Zahlen handelt. Wenn nicht, wird Abschnitt "7.2.12 SameValueNonNumber (x, y)" verwendet.
Rusty Core

101

In PHP und JavaScript ist es ein strikter Gleichheitsoperator. Das heißt, es werden sowohl Typ als auch Werte verglichen.


10
@ David: richtig. Deshalb ist diese Antwort ungenau (oder sogar falsch)
Philippe Leybaert

7
@David var a = {}, b = {}; a == bgibt false zurück.
Nyuszika7h

6
Ja: Zwei verschiedene Objekte mit demselben Typ und Wert vergleichen false, dh diese Antwort ist einfach falsch. Warum hat es 50 Upvotes?
Alexis

4
Mir ist klar, dass dies alt ist, aber zu klären, warum diese Antwort immer noch "richtig" ist, liegt daran, dass im Beispiel var a = {}, b = {};zwar beide aund bzwar beide ein Objekt sind, sie aber technisch gesehen nicht den gleichen Wert haben. Sie sind verschiedene Instanzen. Beachten Sie, dass sich das Vergleichen von Instanzen anders verhält als das Vergleichen von Grundelementen. Was wahrscheinlich zu dieser Verwirrung beiträgt. Sie sehen ein ähnliches Vergleichsverhalten, wenn Sie eine Instanzversion primitiver Datentypen verwenden. ZB new String('asdf')oder new Number(5). Beispiel: new Number(5) == new Number(5)ist falsch, obwohl sie den gleichen Wert haben.
Norman Breau

1
Wir alle vergessen, dass ein Verweis auf ein Objekt tatsächlich ein Werttyp ist, da er ein Zeiger auf einen Speichersteckplatz ist. Der Objektvergleich vergleicht nicht den "Wert des Objekts", sondern ob beide Zeiger gleich sind, was bedeuten würde, dass sie auf denselben Speicherplatz verweisen. Dies ist ein sehr subtiler Unterschied beim Vergleichen von Typen, da der Operator "===" wirklich sagen muss, "ob Typ, Wert und Verweis auf das Objekt im Speicher identisch sind".
Stokely

101

Ich habe dies in Firefox mit Firebug mit folgendem Code getestet :

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

und

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

Meine Ergebnisse (jeweils fünfmal getestet und gemittelt):

==: 115.2
===: 114.4

Ich würde also sagen, dass der winzige Unterschied (das sind über 100000 Iterationen, denken Sie daran) vernachlässigbar ist. Leistung ist kein Grund dazu ===. Geben Sie Sicherheit ein (so sicher wie in JavaScript), und die Codequalität ist.


3
Mehr als Typensicherheit möchten Sie logische Korrektheit - manchmal möchten Sie, dass die Dinge wahr sind, wenn Sie nicht ==einverstanden sind.
rpjohnst

4
Wie vergleichen sich diese nun, wenn es eine tatsächliche Typenzusammensetzung für den ==Bediener gibt? Denken Sie daran, dann gibt es einen Leistungsschub.
Hubert OG

2
GROSSER Unterschied bei ordnungsgemäßer Prüfung aus den oben genannten Gründen, um nur die Typungleichheit schneller zu überprüfen. jsfiddle.net/4jhuxkb2
Doug Morrow

Sie messen die Leistung von so etwas in Operationen / Sekunde, nicht einen einzelnen Test in einem einzelnen Browser (einer mit einem Marktanteil von etwa 5%) mit console.time (), während Sie einen Test verwenden, der keinen Typzwang erfordert (der gesamte Grund) es ist langsamer) berücksichtigt. Dies ist ein völlig bedeutungsloser Test. Sie haben Recht, dass Leistung nicht der Grund für eine ===Übernutzung ist, ==aber Sie irren sich, dass ihre Leistung im Wesentlichen gleich ist und dass Sie denken würden, dass dieser Test beweist, dass und dass viele andere Menschen zustimmten, für mich völlig absurd ist.
Stephen M Irving

97

In JavaScript bedeutet es den gleichen Wert und Typ.

Zum Beispiel,

4 == "4" // will return true

aber

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

87

Der Operator === wird als strenger Vergleichsoperator bezeichnet und unterscheidet sich vom Operator == .

Nehmen wir 2 Vars a und b.

Damit "a == b" als wahr ausgewertet wird, müssen a und b den gleichen Wert haben .

Im Fall von "a === b" müssen a und b den gleichen Wert und auch den gleichen Typ haben, damit sie als wahr ausgewertet werden.

Nehmen Sie das folgende Beispiel

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");
}

Zusammenfassend ; Die Verwendung des Operators == kann in Situationen, in denen Sie dies nicht möchten, mit true = true auswerten Operators sicherer.

Im 90% -Nutzungsszenario spielt es keine Rolle, welches Sie verwenden, aber es ist praktisch, den Unterschied zu kennen, wenn Sie eines Tages ein unerwartetes Verhalten feststellen.


82

Warum ==ist das so unvorhersehbar?

Was bekommen Sie, wenn Sie eine leere Zeichenfolge ""mit der Zahl Null vergleichen 0?

true

Ja, das stimmt == einer leeren Zeichenfolge und die Zahl Null ist dieselbe Zeit.

Und es endet nicht dort, hier ist noch eines:

'0' == false // true

Mit Arrays wird es wirklich komisch.

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

Dann seltsamer mit Saiten

[1,2,3] == '1,2,3' // true - REALLY?!
'\r\n\t' == 0 // true - Come on!

Es wird schlimmer:

Wann ist gleich nicht gleich?

let A = ''  // empty string
let B = 0   // zero
let C = '0' // zero string

A == B // true - ok... 
B == C // true - so far so good...
A == C // **FALSE** - Plot twist!

Lassen Sie mich das noch einmal sagen:

(A == B) && (B == C) // true
(A == C) // **FALSE**

Und das ist nur das verrückte Zeug, das man mit Primitiven bekommt.

Es ist eine ganz neue Ebene der Verrücktheit, wenn Sie ==mit Objekten verwenden.

An diesem Punkt wundern Sie sich wahrscheinlich ...

Warum passiert das?

Nun, es liegt daran, dass im Gegensatz zu "Triple Equals" ( ===) nur geprüft wird, ob zwei Werte gleich sind.

==macht eine ganze Reihe anderer Sachen .

Es hat eine spezielle Behandlung für Funktionen, eine spezielle Behandlung für Nullen, undefinierte Zeichenfolgen, wie Sie es nennen.

Es wird ziemlich verrückt.

Wenn Sie versuchen würden, eine Funktion zu schreiben, die das ==tut , was sie tut, würde sie ungefähr so ​​aussehen:

function isEqual(x, y) { // if `==` were a function
    if(typeof y === typeof x) return y === x;
    // treat null and undefined the same
    var xIsNothing = (y === undefined) || (y === null);
    var yIsNothing = (x === undefined) || (x === null);

    if(xIsNothing || yIsNothing) return (xIsNothing && yIsNothing);

    if(typeof y === "function" || typeof x === "function") {
        // if either value is a string 
        // convert the function into a string and compare
        if(typeof x === "string") {
            return x === y.toString();
        } else if(typeof y === "string") {
            return x.toString() === y;
        } 
        return false;
    }

    if(typeof x === "object") x = toPrimitive(x);
    if(typeof y === "object") y = toPrimitive(y);
    if(typeof y === typeof x) return y === x;

    // convert x and y into numbers if they are not already use the "+" trick
    if(typeof x !== "number") x = +x;
    if(typeof y !== "number") y = +y;
    // actually the real `==` is even more complicated than this, especially in ES6
    return x === y;
}

function toPrimitive(obj) {
    var value = obj.valueOf();
    if(obj !== value) return value;
    return obj.toString();
}

Was bedeutet das?

Es bedeutet == ist kompliziert.

Da es kompliziert ist, ist es schwer zu wissen, was passieren wird, wenn Sie es verwenden.

Was bedeutet, dass Sie mit Fehlern enden könnten.

Die Moral der Geschichte lautet also ...

Machen Sie Ihr Leben weniger kompliziert.

Verwenden Sie ===anstelle von ==.

Das Ende.


Dein looseEqualist falsch. Function == Function.toString()ist wahr, aber looseEqual(Function, Function.toString())falsch. Ich bin mir nicht sicher, warum Sie Funktionen am Anfang herausfiltern.
Oriol

@Oriol Sie hatten Recht, ich habe den Code aktualisiert, um dies zu berücksichtigen. Zu Ihrer Information, basierend auf meinen Tests, war es nicht genug, den Filter für "Funktionen" zu entfernen, stattdessen mussten "Funktionen" insgesamt anders behandelt werden.
Luis Perez

Beachten Sie, dass die Spezifikation Funktionen nicht anders behandelt, sondern nur Objekte sind. Das Problem scheint, dass Sie sich darauf verlassen, typeof x === "object"zu überprüfen, ob es sich um ein Objekt handelt, aber `typeof funktioniert nur für Nicht-Null-Grundelemente. Sie könnten an meiner Liste der richtigen Möglichkeiten
Oriol

Ich habe versucht, Funktionen und Objekte gleich zu behandeln, aber festgestellt, dass die Ergebnisse falsch waren. Wenn beispielsweise Funktionen wie Objekte behandelt würden, würde ein Vergleich einer Funktion mit einem Objekt, das die Funktion valueOf () oder toString () implementiert, die der Funktion entspricht, übergeben, in Wirklichkeit jedoch nicht. Beispiel: (function blah() { console.log("test"); }) != {valueOf:function(){return "function blah() { console.log(\"test\"); }";}}- Schauen Sie sich diese JS-Geige an, die alle Tests ausführt : jsfiddle.net/luisperezphd/7k6gcn6g (dort 1.225 Testpermutationen )
Luis Perez

1
Sie haben Recht, großartige Beobachtungen. Dies unterstreicht den Hauptpunkt, ==der viele Dinge bewirkt, die es sehr schwierig machen, die Ergebnisse ===vorherzusehen, während es viel einfacher und vorhersehbarer ist, was einer der Hauptgründe ===für die empfohlene Wahl ist. (Ich werde der Antwort eine Notiz hinzufügen, in der Ihr Punkt erwähnt wird)
Luis Perez

81

===prüft, ob die gleichen Seiten in Typ und Wert gleich sind .


Beispiel:

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

Allgemeines Beispiel:

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

Ein weiteres häufiges Beispiel:

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

Viele Male eine nicht typisierte Check wäre praktisch , weil Sie den Wert egal , wenn entweder ist undefined, null, 0 oder""


7
auch'string' !== 'number'
Homer

71

Ablaufdiagramm für die Ausführung von Javascript für strikte Gleichheit / Vergleich '==='

Javascript strenge Gleichheit

Flussdiagramm der Javascript-Ausführung für nicht strikte Gleichheit / Vergleich '=='

Javascript Ungleichheit


Ich verstehe nicht, warum der stringPfeil auf das große graue Kästchen zeigt. Soll das bedeuten, dass der Unterbrecher die Zeichenfolge in eine Zahl umwandelt?
vsync

@vsync Zeigt auf die Zeichenfolgenoption im grauen Feld, dh Zeichenfolge -> # || NaN. Javascript ist keine Typ-Skript-Sprache, dh es kann grundsätzlich jede Art von Variable haben. Es wird also auf diese graue Box hingewiesen.
Samar Panda

Ich habe einfach gefragt, ob es sich um Casting-Zwecke handelt, da das stringmit einem Typ verglichen werden soll. numberDer Unterbrecher prüft also, mit was der String verglichen werden soll, und wirft den String entsprechend um.
vsync

1
Das große graue Kästchen wird ToNumberzurückgegeben, wenn verschiedene Typen angegeben werden. Wenn also eine Zeichenfolge angegeben wird, wird nur die letzte Option ausgewählt (und in eine Zahl konvertiert). ==wird ToNumbernur in den Fällen string == numberoder boolean == anythingdarüber (und nur auf dem string/ boolean) verwendet. Dies bedeutet, ==dass niemals konvertiert wird undefinedoder nullobwohl sie sich in der grauen Box befinden. (Für jede Kombination von einem undefinedoder nullbeiden ==wird immer zurückgegeben true. Auch spielt es keine Rolle, ob sich ein Wert auf der linken oder rechten Seite befindet, ==(und ===) gibt das gleiche Ergebnis zurück.)
user2033427

55

JavaScript === vs == .

0==false   // true
0===false  // false, because they are of a different type
1=="1"     // true, auto type coercion
1==="1"    // false, because they are of a different type

54

Dies bedeutet Gleichheit ohne Typzwang. Typzwang bedeutet, dass JavaScript keine anderen Datentypen automatisch in Zeichenfolgendatentypen konvertiert

0==false   // true,although they are different types

0===false  // false,as they are different types

2=='2'    //true,different types,one is string and another is integer but 
            javaScript convert 2 to string by using == operator 

2==='2'  //false because by using === operator ,javaScript do not convert 
           integer to string 

2===2   //true because both have same value and same types 

48

In einem typischen Skript gibt es keinen Leistungsunterschied. Wichtiger ist möglicherweise die Tatsache, dass tausend "===" 1 KB schwerer als tausend "==" sind :) JavaScript-Profiler können Ihnen sagen, ob es in Ihrem Fall einen Leistungsunterschied gibt.

Aber persönlich würde ich tun, was JSLint vorschlägt. Diese Empfehlung gibt es nicht wegen Leistungsproblemen, sondern weil Typ Zwangsmittel ('\t\r\n' == 0)wahr sind.


4
Nicht immer wahr. Bei der gzip-Komprimierung wäre der Unterschied nahezu vernachlässigbar.
Daniel X Moore

1
Stimmen Sie zu, aber tausend "===" bedeutet auch 10 Tausend Codezeilen, also 1 KB mehr oder weniger ...;)
Jonny

Wenn Sie sich Sorgen um die Größe machen, tauschen Sie einfach alle Ihre == mit === aus und verwenden Sie dann einen in av eval verpackten regulären Ausdruck, um ihn zurückzuschalten

46

Der gleiche Vergleichsoperator == ist verwirrend und sollte vermieden werden.

Wenn Sie damit leben MÜSSEN , denken Sie an die folgenden drei Dinge:

  1. Es ist nicht transitiv: (a == b) und (b == c) führen nicht zu (a == c)
  2. Es schließt sich gegenseitig für seine Negation aus: (a == b) und (a! = B) halten immer entgegengesetzte Boolesche Werte mit allen a und b.
  3. Im Zweifelsfall lernen Sie auswendig die folgende Wahrheitstabelle:

GLEICHE OPERATOR-WAHRHEITSTABELLE IN JAVASCRIPT

  • Jede Zeile in der Tabelle besteht aus 3 miteinander "gleichen" Werten, was bedeutet, dass 2 beliebige Werte unter Verwendung des Gleichheitszeichens * gleich sind.

** STRANGE: Beachten Sie, dass zwei beliebige Werte in der ersten Spalte in diesem Sinne nicht gleich sind. **

''       == 0 == false   // Any two values among these 3 ones are equal with the == operator
'0'      == 0 == false   // Also a set of 3 equal values, note that only 0 and false are repeated
'\t'     == 0 == false   // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
'\r'     == 0 == false   // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
'\n'     == 0 == false   // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
'\t\r\n' == 0 == false   // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

null == undefined  // These two "default" values are not-equal to any of the listed values above
NaN                // NaN is not equal to any thing, even to itself.

39

Es ist unwahrscheinlich, dass zwischen den beiden Vorgängen in Ihrer Verwendung Leistungsunterschiede bestehen. Es ist keine Typkonvertierung durchzuführen, da beide Parameter bereits vom selben Typ sind. Beide Operationen haben einen Typvergleich, gefolgt von einem Wertevergleich.


38

Ja! Es ist wichtig.

===Der Operator in Javascript überprüft sowohl den Wert als auch den Typ, wobei der ==Operator nur den Wert überprüft (führt bei Bedarf eine Typkonvertierung durch) .

Geben Sie hier die Bildbeschreibung ein

Sie können es leicht testen. Fügen Sie den folgenden Code in eine HTML-Datei ein und öffnen Sie ihn im Browser

<script>

function onPageLoad()
{
    var x = "5";
    var y = 5;
    alert(x === 5);
};

</script>

</head>

<body onload='onPageLoad();'>

Sie werden ' false ' in Alarmbereitschaft erhalten. Ändern Sie nun die onPageLoad()Methode alert(x == 5);so, dass sie wahr wird .


33

=== Der Operator überprüft die Werte sowie die Typen der Variablen auf Gleichheit.

== Der Operator überprüft nur den Wert der Variablen auf Gleichheit.


32

Es ist ein strenger Kontrolltest.

Dies ist besonders dann gut, wenn Sie zwischen 0 und false und null prüfen.

Zum Beispiel, wenn Sie haben:

$a = 0;

Dann:

$a==0; 
$a==NULL;
$a==false;

Alles gibt true zurück und Sie möchten dies möglicherweise nicht. Angenommen, Sie haben eine Funktion, die den 0. Index eines Arrays oder bei einem Fehler false zurückgeben kann. Wenn Sie mit "==" false prüfen, erhalten Sie ein verwirrendes Ergebnis.

Also mit dem gleichen wie oben, aber einem strengen Test:

$a = 0;

$a===0; // returns true
$a===NULL; // returns false
$a===false; // returns false

3
In JavaScript ist dies völlig falsch und fälschlicherweise unvollständig. 0 != null. -1
Ry-

31

JSLint gibt Ihnen manchmal unrealistische Gründe, um Dinge zu ändern. ===hat genau die gleiche Leistung wie== ob die Typen bereits gleich sind.

Es ist nur dann schneller, wenn die Typen nicht identisch sind. In diesem Fall wird nicht versucht, Typen zu konvertieren, sondern es wird direkt ein false zurückgegeben.

Also, IMHO, JSLint vielleicht verwendet , um neuen Code zu schreiben, aber nutzlos Überoptimierung sollte unter allen Umständen vermieden werden.

Das heißt, es gibt keinen Grund ==, ===in einem Scheck wie zu ändernif (a == 'test') wenn Sie wissen, dass a nur ein String sein kann.

Wenn Sie so viel Code ändern, verschwenden Sie Zeit für Entwickler und Prüfer und erzielen nichts.


30

Einfach

==bedeutet Vergleich zwischen Operanden mit type conversion

&

===bedeutet Vergleich zwischen Operanden ohne type conversion

Typkonvertierung in JavaScript bedeutet, dass JavaScript alle anderen Datentypen automatisch in Zeichenfolgendatentypen konvertiert.

Zum Beispiel:

123=='123'   //will return true, because JS convert integer 123 to string '123'
             //as we used '==' operator 

123==='123' //will return false, because JS do not convert integer 123 to string 
            //'123' as we used '===' operator 

26

Ein einfaches Beispiel ist

2 == '2'  -> true, values are SAME because of type conversion.

2 === '2'  -> false, values are NOT SAME because of no type conversion.

25

Die beiden oben genannten Antworten == bedeuten Gleichheit und === Identität. Leider ist diese Aussage falsch.

Wenn beide Operanden von == Objekte sind, werden sie verglichen, um festzustellen, ob sie dasselbe Objekt sind. Wenn beide Operanden auf dasselbe Objekt zeigen, gibt der gleiche Operator true zurück. Ansonsten sind die beiden nicht gleich.

var a = [1, 2, 3];  
var b = [1, 2, 3];  
console.log(a == b)  // false  
console.log(a === b) // false  

Im obigen Code werden sowohl == als auch === falsch, da a und b nicht dieselben Objekte sind.

Das heißt: Wenn beide Operanden von == Objekte sind, verhält sich == genauso wie ===, was auch Identität bedeutet. Der wesentliche Unterschied zwischen diesen beiden Operatoren besteht in der Typkonvertierung. == hat eine Konvertierung, bevor die Gleichheit überprüft wird, === jedoch nicht.


24

Als Faustregel würde ich im Allgemeinen ===anstelle von ==(und !==anstelle von verwenden!= ) verwenden.

Die Gründe werden in den obigen Antworten erläutert und auch Douglas Crockford ist ziemlich klar darüber ( JavaScript: The Good Parts ).

Es gibt jedoch eine einzige Ausnahme : Dies == nullist eine effiziente Methode, um zu überprüfen, ob "null oder undefiniert" ist:

if( value == null ){
    // value is either null or undefined
}

Zum Beispiel verwendet jQuery 1.9.1 dieses Muster 43 Mal, und der JSHint-Syntaxprüfer bietet sogar daseqnull aus diesem Grund entspannende Option.

Aus dem jQuery-Styleguide :

Strenge Gleichheitsprüfungen (===) sollten zugunsten von == verwendet werden. Die einzige Ausnahme ist die Überprüfung auf undefiniert und null über null.

// Check for both undefined and null values, for some important reason. 
undefOrNull == null;

22

Das Problem ist, dass Sie leicht in Schwierigkeiten geraten können, da JavaScript viele implizite Konvertierungen hat, was bedeutet ...

var x = 0;
var isTrue = x == null;
var isFalse = x === null;

Was ziemlich bald zum Problem wird. Das beste Beispiel dafür, warum implizite Konvertierung "böse" ist, kann diesem Code in MFC / C ++ entnommen werden, der aufgrund einer impliziten Konvertierung von CString nach HANDLE, einem Zeigertyp vom Typ typedef, tatsächlich kompiliert wird.

CString x;
delete x;

Was offensichtlich zur Laufzeit sehr undefinierte Dinge tut ...

Google für implizite Konvertierungen in C ++ und STL , um einige der Argumente dagegen zu erhalten ...


2
0 == nullist falsch.
Garrett


21

Gleichstellungsvergleich:

Operator ==

Gibt true zurück, wenn beide Operanden gleich sind. Die Operanden werden vor dem Vergleich in denselben Typ konvertiert.

>>> 1 == 1
true
>>> 1 == 2
false
>>> 1 == '1'
true

Gleichheits- und Typvergleich:

Operator ===

Gibt true zurück, wenn beide Operanden gleich und vom gleichen Typ sind. Es ist im Allgemeinen besser und sicherer, wenn Sie dies vergleichen, da es keine Konvertierungen vom Typ hinter den Kulissen gibt.

>>> 1 === '1'
false
>>> 1 === 1
true

20

Hier ist eine praktische Vergleichstabelle, die die Konvertierungen und die Unterschiede zwischen ==und zeigt ===.

Wie die Schlussfolgerung besagt:

"Verwenden Sie drei Gleichheitswerte, es sei denn, Sie verstehen die Konvertierungen, die für zwei Gleichheitswerte stattfinden, vollständig."

http://dorey.github.io/JavaScript-Equality-Table/


20

null und undefiniert sind nichts, das heißt,

var a;
var b = null;

Hier aund bhaben keine Werte. Während 0, false und '' alle Werte sind. Allen gemeinsam ist, dass es sich bei allen um falsche Werte handelt, was bedeutet, dass sie alle falsche Bedingungen erfüllen .

Die 0, false und '' bilden zusammen eine Untergruppe. Andererseits bilden null und undefiniert die zweite Untergruppe. Überprüfen Sie die Vergleiche im folgenden Bild. null und undefiniert wären gleich. Die anderen drei würden einander gleich sein. Sie werden jedoch alle in JavaScript als falsche Bedingungen behandelt.

Geben Sie hier die Bildbeschreibung ein

Dies ist dasselbe wie bei jedem Objekt (wie {}, Arrays usw.). Nicht leere Zeichenfolgen und Boolesche Werte sind alles wahrheitsgemäße Bedingungen. Aber sie sind nicht alle gleich.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.