Leere Arrays scheinen gleichzeitig wahr und falsch zu sein

Lesezeit: 11 Minuten

Leere Arrays scheinen gleichzeitig wahr und falsch zu sein
Patonza

Leere Arrays sind wahr, aber sie sind auch gleich falsch.

var arr = [];
console.log('Array:', arr);
if (arr) console.log("It's true!");
if (arr == false) console.log("It's false!");
if (arr && arr == false) console.log("...what??");

Ich denke, das liegt an der impliziten Konvertierung, die vom Gleichheitsoperator durchgeführt wird.

Kann jemand erklären, was hinter den Kulissen vor sich geht?

  • Hier ist ein ähnlicher Thread, der etwas Licht ins Dunkel bringen sollte: stackoverflow.com/questions/4226101/…

    – Rion Williams

    30. März 2011 um 20:01 Uhr

  • Beachten Sie, dass arr == true wertet nicht zu wahr 😉

    – Michael Krelin – Hacker

    30. März 2011 um 20:09 Uhr

  • Wow … gerade als du dachtest, du hättest das alles erledigt.

    – Harfe

    30. März 2011 um 20:14 Uhr

  • @DjebbZ beide ([] == []) und ([] === []) sollte immer als false ausgewertet werden! Arrays sind Objekte und werden durch Referenzgleichheit verglichen; zwei Array-Variablen können den gleichen Inhalt enthalten, sich aber dennoch unterscheiden.

    – Joe Lee-Moyet

    20. Dezember 2012 um 18:32 Uhr

  • Wenn Sie die Leerheit eines Arrays testen möchten, verwenden Sie NICHT arr === [], da dies IMMER false zurückgibt, da die rechte Seite ein neues Array instanziiert und die Variable auf der linken Seite nicht auf etwas verweisen kann, das Sie gerade erstellt haben. Das Testen der Leere sollte durch Nachschlagen erfolgen arr.length === 0.

    – Kyle Baker

    22. August 2016 um 16:43 Uhr

1646253309 947 Leere Arrays scheinen gleichzeitig wahr und falsch zu sein
Platzhalter

Sie testen hier verschiedene Dinge.

if (arr) called on object (Array ist eine Instanz von Object in JS) prüft, ob das Objekt vorhanden ist, und gibt true/false zurück.

Wenn du anrufst if (arr == false) du vergleichst Werte dieses Objekts und des Primitivs false Wert. Im Inneren, arr.toString() aufgerufen, die einen leeren String zurückgibt "".

Das ist weil toString aufgerufen bei Array-Rückgaben Array.join()und eine leere Zeichenfolge ist einer der falschen Werte in JavaScript.

  • Kannst du erklären warumBoolean([]) kehrt zurück true?

    – Devy

    2. Juni 2016 um 20:38 Uhr


  • Das ist Konvention, wenn Objekte in JS auf Boolean gezwungen werden, werden sie immer auf TRUE gezwungen. Schauen Sie sich die Tabelle “Boolescher Kontext” an unter: javascript.info/tutorial/object-conversion

    – Niki

    7. Juni 2016 um 2:04 Uhr

  • @Devy Alle Objekte in JavaScript sind wahr, daher ist die Konvertierung aller Objekte in Boolean wahr. Sehen 2ality.com/2013/08/objects-truthy.html

    – Thompson

    17. Oktober 2016 um 21:27 Uhr

1646253310 745 Leere Arrays scheinen gleichzeitig wahr und falsch zu sein
Wayne

Bezüglich der Linie:

if (arr == false) console.log("It's false!");

Vielleicht helfen diese:

console.log(0 == false) // true
console.log([] == 0) // true
console.log([] == "") // true

Ich glaube, was passiert, ist, dass der boolesche Wert false dazu gezwungen wird 0 zum Vergleich mit einem Objekt (linke Seite). Das Objekt wird in einen String (den leeren String) umgewandelt. Dann wird auch der leere String in eine Zahl gezwungen, nämlich Null. Und so ist der letzte Vergleich 0 == 0welches ist true.

Bearbeiten: Sehen dieser Abschnitt der Spezifikation für Details darüber, wie das genau funktioniert.

Hier ist, was passiert, beginnend mit Regel Nr. 1:

1. Wenn sich Typ(x) von Typ(y) unterscheidet, gehen Sie zu Schritt 14.

Die nächste Regel, die gilt, ist Nr. 19:

19. Wenn Type(y) Boolean ist, gib das Ergebnis des Vergleichs x == ToNumber(y) zurück.

Das Ergebnis von ToNumber(false) ist 0also haben wir jetzt:

[] == 0

Auch hier fordert uns Regel Nr. 1 auf, zu Schritt Nr. 14 zu springen, aber der nächste Schritt, der tatsächlich gilt, ist Nr. 21:

21. Wenn Type(x) Object ist und Type(y) entweder String oder Number ist, gib das Ergebnis des Vergleichs ToPrimitive(x)== y zurück.

Das Ergebnis von ToPrimitive([]) ist der leere String, also haben wir jetzt:

"" == 0

Auch hier fordert uns Regel Nr. 1 auf, zu Schritt Nr. 14 zu springen, aber der nächste Schritt, der tatsächlich gilt, ist Nr. 17:

17. Wenn Type(x) String ist und Type(y) Number ist, gib das Ergebnis des Vergleichs ToNumber(x)== y zurück.

Das Ergebnis von ToNumber("") ist 0was uns belässt:

0 == 0

Jetzt haben beide Werte den gleichen Typ, also gehen die Schritte von #1 bis #7 weiter, was besagt:

7. Wenn x derselbe Zahlenwert wie y ist, wird wahr zurückgegeben.

Also kehren wir zurück true.

In Kürze:

ToNumber(ToPrimitive([])) == ToNumber(false)

  • Tolle Referenz! Um Verwirrung zu vermeiden, könnte es hilfreich sein zu erwähnen, dass der Grund „die nächste anwendbare Regel ist Nr Werte verglichen werden.

    – Sean die Bohne

    8. Juli 2015 um 14:06 Uhr

  • Schöne Erklärung. Es ist mir rätselhaft, dass leere Arrays als wahr angesehen werden, 0 ist falsch, und doch [] == 0 ist wahr. Ich verstehe, wie dies geschieht, basierend auf Ihrer Erklärung der Spezifikation, aber es scheint aus logischer Sicht ein seltsames Sprachverhalten zu sein.

    – groß_29

    17. Januar 2018 um 22:16 Uhr


1646253310 106 Leere Arrays scheinen gleichzeitig wahr und falsch zu sein
cjg

Um Waynes Antwort zu ergänzen und zu versuchen zu erklären, warum ToPrimitive([]) kehrt zurück "", lohnt es sich, zwei mögliche Arten von Antworten auf die „Warum“-Frage in Betracht zu ziehen. Die erste Art der Antwort lautet: „Weil die Spezifikation besagt, dass sich JavaScript so verhalten wird.“ In der ES5-Spezifikation Abschnitt 9.1die das Ergebnis von ToPrimitive als Standardwert für ein Objekt beschreibt:

Der Standardwert eines Objekts wird durch Aufrufen von abgerufen [[DefaultValue]]interne Methode des Objekts, wobei der optionale Hinweis PreferredType übergeben wird.

Abschnitt 8.12.8 beschreibt die [[DefaultValue]] Methode. Diese Methode akzeptiert einen „Hinweis“ als Argument, und der Hinweis kann entweder „String“ oder „Number“ sein. Um die Sache zu vereinfachen, indem auf einige Details verzichtet wird, wenn der Hint String ist, dann [[DefaultValue]] gibt den Wert von zurück toString() wenn es existiert und einen primitiven Wert zurückgibt und andernfalls den Wert von zurückgibt valueOf(). Wenn der Hinweis Nummer ist, sind die Prioritäten von toString() und valueOf() sind damit umgekehrt valueOf() wird zuerst aufgerufen und sein Wert zurückgegeben, wenn es sich um ein Primitiv handelt. Also, ob [[DefaultValue]] gibt das Ergebnis von zurück toString() oder valueOf() hängt vom angegebenen PreferredType für das Objekt ab und davon, ob diese Funktionen primitive Werte zurückgeben oder nicht.

Der Standard valueOf() Die Objektmethode gibt nur das Objekt selbst zurück, was bedeutet, dass, sofern eine Klasse die Standardmethode nicht überschreibt, valueOf() gibt nur das Objekt selbst zurück. Dies ist der Fall für Array. [].valueOf() gibt das Objekt zurück [] selbst. Seit ein Array Objekt ist kein Primitiv, das [[DefaultValue]] Hinweis ist irrelevant: Der Rückgabewert für ein Array ist der Wert von toString().

Zitieren David Flanagans JavaScript: Der endgültige Leitfadendas übrigens ein hervorragendes Buch ist, das jedermanns erste Anlaufstelle sein sollte, um Antworten auf diese Art von Fragen zu erhalten:

Die Details dieser Objekt-zu-Zahl-Konvertierung erklären, warum ein leeres Array in die Zahl 0 konvertiert wird und warum ein Array mit einem einzelnen Element auch in eine Zahl konvertiert werden kann. Arrays erben die Standardmethode valueOf(), die ein Objekt statt eines primitiven Werts zurückgibt, sodass die Umwandlung von Arrays in Zahlen auf der Methode toString() beruht. Leere Arrays werden in den leeren String konvertiert. Und die leere Zeichenfolge wird in die Zahl 0 konvertiert. Ein Array mit einem einzelnen Element wird in dieselbe Zeichenfolge konvertiert wie dieses eine Element. Wenn ein Array eine einzelne Zahl enthält, wird diese Zahl in eine Zeichenfolge und dann wieder in eine Zahl umgewandelt.

Die zweite Art der Antwort auf die „Warum“-Frage, außer „weil die Spezifikation sagt“, gibt eine Erklärung dafür, warum das Verhalten aus der Designperspektive sinnvoll ist. Zu diesem Thema kann ich nur spekulieren. Erstens, wie würde man ein Array in eine Zahl umwandeln? Die einzige vernünftige Möglichkeit, die mir einfällt, wäre, ein leeres Array in 0 und jedes nicht leere Array in 1 zu konvertieren. Aber wie Waynes Antwort zeigte, wird ein leeres Array für viele Arten von Vergleichen sowieso in 0 konvertiert. Darüber hinaus ist es schwierig, sich einen vernünftigen primitiven Rückgabewert für Array.valueOf() vorzustellen. Man könnte also argumentieren, dass es einfach sinnvoller ist, es zu haben Array.valueOf() sei der Standardwert und gebe das Array selbst zurück, führend toString() das von ToPrimitive verwendete Ergebnis sein. Es ist einfach sinnvoller, ein Array in einen String statt in eine Zahl umzuwandeln.

Darüber hinaus ermöglicht diese Designentscheidung, wie das Flanagan-Zitat andeutet, bestimmte Arten von vorteilhaften Verhaltensweisen. Zum Beispiel:

var a = [17], b = 17, c=1;
console.log(a==b);      // <= true
console.log(a==c);      // <= false

Dieses Verhalten ermöglicht es Ihnen, ein Einzelelement-Array mit Zahlen zu vergleichen und das erwartete Ergebnis zu erhalten.

console.log('-- types: undefined, boolean, number, string, object --');
console.log(typeof undefined);  // undefined
console.log(typeof null);       // object
console.log(typeof NaN);        // number
console.log(typeof false);      // boolean
console.log(typeof 0);          // number
console.log(typeof "");         // string
console.log(typeof []);         // object
console.log(typeof {});         // object

console.log('-- Different values: NotExist, Falsy, NaN, [], {} --');
console.log('-- 1. NotExist values: undefined, null have same value --');
console.log(undefined == null); // true

console.log('-- 2. Falsy values: false, 0, "" have same value --');
console.log(false == 0);        // true
console.log(false == "");       // true
console.log(0 == "");           // true

console.log('-- 3. !NotExist, !Falsy, and !NaN return true --');
console.log(!undefined);        // true
console.log(!null);             // true

console.log(!false);            // true
console.log(!"");               // true
console.log(!0);                // true

console.log(!NaN);              // true

console.log('-- 4. [] is not falsy, but [] == false because [].toString() returns "" --');
console.log(false == []);       // true
console.log([].toString());     // ""

console.log(![]);               // false

console.log('-- 5. {} is not falsy, and {} != false, because {}.toString() returns "[object Object]" --');
console.log(false == {});       // false
console.log({}.toString());     // [object Object]

console.log(!{});               // false

console.log('-- Comparing --');
console.log('-- 1. string will be converted to number or NaN when comparing with a number, and "" will be converted to 0 --');
console.log(12 < "2");          // false
console.log("12" < "2");        // true
console.log("" < 2);            // true

console.log('-- 2. NaN can not be compared with any value, even if NaN itself, always return false --');
console.log(NaN == NaN);        // false

console.log(NaN == null);       // false
console.log(NaN == undefined);  // false
console.log(0 <= NaN);          // false
console.log(0 >= NaN);          // false
console.log(undefined <= NaN);  // false
console.log(undefined >= NaN);  // false
console.log(null <= NaN);       // false
console.log(null >= NaN);       // false

console.log(2 <= "2a");         // false, since "2a" is converted to NaN
console.log(2 >= "2a");         // false, since "2a" is converted to NaN

console.log('-- 3. undefined can only == null and == undefined, and can not do any other comparing even if <= undefined --');
console.log(undefined == null);         // true
console.log(undefined == undefined);    // true

console.log(undefined == "");           // false
console.log(undefined == false);        // false
console.log(undefined <= undefined);    // false
console.log(undefined <= null);         // false
console.log(undefined >= null);         // false
console.log(0 <= undefined);            // false
console.log(0 >= undefined);            // false

console.log('-- 4. null will be converted to "" when <, >, <=, >= comparing --');
console.log(12 <= null);        // false
console.log(12 >= null);        // true
console.log("12" <= null);      // false
console.log("12" >= null);      // true

console.log(0 == null);         // false
console.log("" == null);        // false

console.log('-- 5. object, including {}, [], will be call toString() when comparing --');
console.log(12 < {});           // false, since {}.toString() is "[object Object]", and then converted to NaN
console.log(12 > {});           // false, since {}.toString() is "[object Object]", and then converted to NaN
console.log("[a" < {});         // true, since {}.toString() is "[object Object]"
console.log("[a" > {});         // false, since {}.toString() is "[object Object]"
console.log(12 < []);           // false, since {}.toString() is "", and then converted to 0
console.log(12 > []);           // true, since {}.toString() is "", and then converted to 0
console.log("[a" < []);         // false, since {}.toString() is ""
console.log("[a" > []);         // true, since {}.toString() is ""

console.log('-- 6. According to 4 and 5, we can get below weird result: --');
console.log(null < []);         // false
console.log(null > []);         // false
console.log(null == []);        // false
console.log(null <= []);        // true
console.log(null >= []);        // true

Leere Arrays scheinen gleichzeitig wahr und falsch zu sein
Thomas

In if (arr) wird es immer als wahr ausgewertet (ToBoolean), wenn arr ein Objekt ist, weil Alle Objekte in JavaScript sind wahr. (Null ist kein Objekt!)

[] == false wird iterativ evaluiert. Zunächst, wenn eine Seite von == primitiv und die andere ein Objekt ist, wandelt es zuerst Objekt in primitiv um und dann beide Seiten in Zahl, wenn beide Seiten es nicht sind string (String-Vergleich wird verwendet, wenn beide Seiten Strings sind). Der Vergleich wird also wie folgt wiederholt: [] == false -> '' == false -> 0 == 0 -> true.

1646253310 44 Leere Arrays scheinen gleichzeitig wahr und falsch zu sein
yqbk

Beispiel:

const array = []
const boolValueOfArray = !!array // true

Es passiert, weil

ToNumber(ToPrimitive([])) == ToNumber(false)  
  1. [] ist leer Array Objekt → ToPrimitive([]) → “” → ToNumber("")0
  2. ToNumber(false) → 0
  3. 0 == 0 → wahr

1646253311 773 Leere Arrays scheinen gleichzeitig wahr und falsch zu sein
Aldee

Ein Array mit Elementen (egal ob 0, false oder ein anderes leeres Array) wird immer aufgelöst true Verwenden von abstraktem Gleichheitsvergleich ==.

1. [] == false; // true, because an empty array has nothing to be truthy about
2. [2] == false; // false because it has at least 1 item
3. [false] == false; // also false because false is still an item
4. [[]] == false; // false, empty array is still an item

Aber mit einem strengen Gleichheitsvergleich ===Sie versuchen, den Inhalt der Variablen sowie ihren Datentyp auszuwerten, weshalb:

1. [] === false; // false, because an array (regardless of empty or not) is not strictly comparable to boolean `false`
2. [] === true; // false, same as above, cannot strictly compare [] to boolean `true`
3. [[]] === false; // true, because see #1

915900cookie-checkLeere Arrays scheinen gleichzeitig wahr und falsch zu sein

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy