Kann (a == 1 && a == 2 && a == 3) jemals als wahr bewerten?

2484

Anmerkung des Moderators: Bitte widersetzen Sie sich dem Drang, den Code zu bearbeiten oder diesen Hinweis zu entfernen. Das Leerzeichenmuster kann Teil der Frage sein und sollte daher nicht unnötig manipuliert werden. Wenn Sie sich im Lager "Leerzeichen sind unbedeutend" befinden, sollten Sie in der Lage sein, den Code unverändert zu akzeptieren.

Ist es jemals möglich, dass in JavaScript (a== 1 && a ==2 && a==3)ausgewertet werden könnte true?

Dies ist eine Interviewfrage, die von einem großen Technologieunternehmen gestellt wird. Es ist vor zwei Wochen passiert, aber ich versuche immer noch, die Antwort zu finden. Ich weiß, dass wir in unserer täglichen Arbeit niemals solchen Code schreiben, aber ich bin neugierig.

Dimpu Aravind Buddha
quelle
9
Kommentare sind nicht für eine ausführliche Diskussion gedacht. Dieses Gespräch wurde in den Chat verschoben .
Täuschung
109
Für die Leute, die anscheinend dafür gestimmt haben, dies als zu weit gefasst zu bezeichnen : Ist das eine Auseinandersetzung mit Javascript, die besagt, dass es zu viele gültige Antworten gibt?
Tomsmeding
24
Einige Leute sitzen herum und philosophieren darüber, was möglich ist. Andere konzentrieren ihre Bemühungen darauf, ob sie tragfähige, geschäftsgerechte Produkte für ihre Kunden entwickeln oder nicht. IMO, diese Frage hat keinen praktischen Nutzen außer der Tatsache, dass Sie diese Art von Fragen niemals in einem Interview stellen oder diese Art von Code schreiben sollten. Deshalb sollte es geschlossen sein. Ich meine wirklich, merkt das Geschäft, dass sie jemandem echtes Geld bezahlt haben, um herumzusitzen und über dieses Zeug zu reden?
P.Brian.Mackey
15
Nach dem Lesen der Antworten lautet die Moral der Geschichte: Nicht verwenden, ==wenn Sie meinen ===, einen Codierungsstandard haben, der Nicht-ASCII-Variablennamen verbietet, und einen Flusenprozess, der die beiden vorherigen Moralvorstellungen durchsetzt.
Jesse C. Slicer
87
Anmerkung des Moderators: Bei Stack Overflow haben sich in der Vergangenheit Antworten auf die betreffende Frage in verschiedenen Sprachen gemeldet. Dies sind Versuche, die Frage zu beantworten, da sie Lösungen für das allgemeine Problem darstellen, wenn auch in einer anderen Sprache. Bitte kennzeichnen Sie sie nicht als "keine Antwort". Bitte verzichten Sie jedoch auch darauf, weitere Antworten in verschiedenen Sprachen zu veröffentlichen. Es gibt einen Grund, warum diese Frage spezifisch für JavaScript ist, wie in den Kommentaren unter einigen dieser anderen Antworten hervorgehoben, und es gibt einen Grund, warum uns unsere sprachspezifischen Fragen gefallen so bleiben.
BoltClock

Antworten:

3323

Wenn Sie nutzen , wie ==funktioniert , könnten Sie einfach ein Objekt mit einer benutzerdefinierten erstellen toString(oder valueOf) Funktion , die ändert , was es jedes Mal wieder ist es so verwendet , dass es erfüllt alle drei Bedingungen.

const a = {
  i: 1,
  toString: function () {
    return a.i++;
  }
}

if(a == 1 && a == 2 && a == 3) {
  console.log('Hello World!');
}


Der Grund, warum dies funktioniert, liegt in der Verwendung des Operators für lose Gleichheit. Wenn bei Verwendung der losen Gleichheit einer der Operanden von einem anderen Typ als der andere ist, versucht die Engine, einen in den anderen zu konvertieren. Bei einem Objekt auf der linken Seite und einer Nummer auf der rechten Seite wird versucht, das Objekt in eine Nummer umzuwandeln, indem zuerst valueOfaufgerufen wird , wenn es aufrufbar ist. Andernfalls wird es angerufen toString. Ich habe toStringin diesem Fall einfach verwendet, weil es mir in den Sinn kam valueOf, sinnvoller wäre. Wenn ich stattdessen eine Zeichenfolge von zurückgegeben hätte toString, hätte die Engine dann versucht, die Zeichenfolge in eine Zahl umzuwandeln, die das gleiche Endergebnis liefert, allerdings mit einem etwas längeren Pfad.

Kevin B.
quelle
70
Könnten Sie dies erreichen, indem Sie die implizite valueOf()Operation ändern ?
Sterling Archer
43
Ja, valueOf funktioniert aus dem gleichen Grund anstelle von toString
Kevin B
4
Kommentare sind nicht für eine ausführliche Diskussion gedacht. Dieses Gespräch wurde in den Chat verschoben .
Täuschung
13
Gemäß dieser einer Reihe Umwandlung wird zunächst so versucht werden , valueOfetwas besser.
Salman A
6
@Pureferret Die linke Seite des Gleichheitsvergleichs ist ein Objekt, keine Zahl. Dass dieses Objekt eine Zahleneigenschaft ihat, stört die Engine nicht. ;)
Tomsmeding
2057

Ich konnte nicht widerstehen - die anderen Antworten sind zweifellos wahr, aber Sie können den folgenden Code wirklich nicht umgehen:

var a = 1;
var a = 2;
var a = 3;
if(aᅠ==1 && a== 2 &&ᅠa==3) {
    console.log("Why hello there!")
}

Beachten Sie den seltsamen Abstand in der ifAnweisung (den ich von Ihrer Frage kopiert habe). Es ist das Hangul mit halber Breite (das ist Koreanisch für diejenigen, die nicht vertraut sind), ein Unicode-Leerzeichen, das vom ECMA-Skript nicht als Leerzeichen interpretiert wird. Dies bedeutet, dass es ein gültiges Zeichen für einen Bezeichner ist. Daher gibt es drei völlig unterschiedliche Variablen, eine mit dem Hangul nach dem a, eine mit dem vor und die letzte mit nur einem. Wenn Sie den Speicherplatz _aus Gründen der Lesbarkeit durch ersetzen , sieht derselbe Code folgendermaßen aus:

var a_ = 1;
var a = 2;
var _a = 3;
if(a_==1 && a== 2 &&_a==3) {
    console.log("Why hello there!")
}

Überprüfen Sie die Validierung auf Mathias 'Variablennamen-Validator . Wenn dieser seltsame Abstand tatsächlich in ihrer Frage enthalten war, bin ich mir sicher, dass dies ein Hinweis für diese Art von Antwort ist.

Tu das nicht. Ernsthaft.

Bearbeiten: Es ist mir aufgefallen, dass (obwohl es nicht erlaubt ist, eine Variable zu starten) die Joiner- Zeichen mit der Breite Null und die Nicht-Joiner- Zeichen mit der Breite Null auch in Variablennamen zulässig sind - siehe Verschleierung von JavaScript mit Zeichen mit der Breite Null - Vor- und Nachteile ? .

Dies würde wie folgt aussehen:

var a= 1;
var a‍= 2; //one zero-width character
var a‍‍= 3; //two zero-width characters (or you can use the other one)
if(a==1&&a‍==2&&a‍‍==3) {
    console.log("Why hello there!")
}

Jeff
quelle
368
Nach dem ungeraden Abstand in der ursprünglichen Frage zu urteilen, denke ich, dass dies genau die Antwort ist, nach der die Interviewfrage gesucht hat - Ausnutzen von Nicht-Leerzeichen, die wie Leerzeichen aussehen. Gute Stelle!
Baracus
18
@Baracus Es war RonJohn, der den seltsamen Abstand in seinem Kommentar zu Kevins Antwort bemerkte, der mich an diese (schreckliche) Technik erinnerte, also kann ich es nicht gutschreiben, sie entdeckt zu haben. Ich war ein bisschen überrascht, dass noch niemand darauf geantwortet hatte, da es vor ein paar Jahren wegen eines Blogposts irgendwo um meine Arbeit ging - ich nahm an, dass es mittlerweile ziemlich allgemein bekannt war.
Jeff
102
Dies ist natürlich als Standardlücke verboten , was auch für Interviews gilt. [Zitat benötigt]
Sanchises
13
In Anbetracht des ursprünglichen Abstands kann es sogar noch schlimmer sein, dh es wurde eine Variable var ᅠ2 = 3verwendet. Also gibt es die drei Variablen aᅠᅠ= 1, ᅠ2 = 3, a = 3( a␣ = 1, ␣2 = 3, a = 3, damit (a␣==1 && a==␣2 && a==3))…
Holger
2
@ AL-zami In zwei der Variablen befindet sich ein zusätzliches Zeichen, das auf Ihrem Bildschirm als Leerzeichen angezeigt wird, aber als Teil des Bezeichners interpretiert wird. Dies bedeutet, dass es drei separate Variablen gibt - a, a und a - das zusätzliche Zeichen ist der Hangul-Raum mit halber Breite.
Jeff
620

ES IST MÖGLICH!

var i = 0;

with({
  get a() {
    return ++i;
  }
}) {
  if (a == 1 && a == 2 && a == 3)
    console.log("wohoo");
}

Dies verwendet einen Getter innerhalb einer withAnweisung, um adrei verschiedene Werte auswerten zu lassen .

... das bedeutet immer noch nicht, dass dies in echtem Code verwendet werden sollte ...

Schlimmer noch, dieser Trick funktioniert auch mit der Verwendung von ===.

  var i = 0;

  with({
    get a() {
      return ++i;
    }
  }) {
    if (a !== a)
      console.log("yep, this is printed.");
  }

Jonas Wilms
quelle
65
Ja, ich habe das Gleiche versucht :) Die richtige Antwort im Interview wäre also: "Es kann in meinem Code nicht passieren , weil ich es nie benutze with."
Pointy
7
@Pointy - Und ich programmiere im strengen Modus, wo withdas nicht erlaubt ist.
jfriend00
6
@Pointy in der akzeptierten Antwort machen sie etwas Ähnliches ohne das, withdamit es passieren kann
Jungkook
2
@jorrit würde niemand verwenden ==. Und ===verhindert die akzeptierte Antwort
Jonas Wilms
4
@ JonasW. Viele Leute benutzen immer noch, ==aber ich habe es withseitdem nicht mehr gesehen ... naja, eigentlich nie außerhalb der JS-Dokumentation, wo es heißt "Bitte benutze das nicht". Wie auch immer, eine schöne Lösung.
Wortwart
516

Beispiel ohne Getter oder valueOf:

a = [1,2,3];
a.join = a.shift;
console.log(a == 1 && a == 2 && a == 3);

Dies funktioniert , weil ==aufruft , toStringdie Anrufe .joinfür Arrays.

Eine andere Lösung, bei Symbol.toPrimitiveder es sich um ein ES6-Äquivalent handelt von toString/valueOf:

let i = 0;
let a = { [Symbol.toPrimitive]: () => ++i };

console.log(a == 1 && a == 2 && a == 3);

Georg
quelle
9
without valueOfNun, es ist indirekter, aber im Grunde das Gleiche.
Jonas Wilms
11
Ich mag diese Lösung wirklich, weil Sie nichts außer der eigenen Join-Funktion des Objekts überschreiben und es nur ein sehr sauberer und leicht zu lesender Hack ist, der die Logik als wahr auswertet.
Alex Pedersen
28
Ehrlich gesagt denke ich, dass dies die beste Antwort ist. Es geht um nichts Außergewöhnliches, nur um das Einstellen einiger Werte. Sehr einfach zu verstehen, auch mit grundlegenden JS-Kenntnissen. Gut gemacht.
Zac Delventhal
14
Das macht so viel Sinn, dass es sich fast nützlich anfühlt.
Andrew
7
Ich wusste , dass die meisten Antworten wären zu missbrauchen toStringoder valueOfaber dies erwischte mich völlig aus der Wache. Sehr klug und ich wusste nicht, dass es .joinintern angerufen wurde , aber es macht total Sinn.
GBarroso
268

Wenn gefragt wird, ob dies möglich ist (nicht MUSS), kann "a" aufgefordert werden, eine Zufallszahl zurückzugeben. Es wäre wahr, wenn es nacheinander 1, 2 und 3 erzeugen würde.

with({
  get a() {
    return Math.floor(Math.random()*4);
  }
}){
  for(var i=0;i<1000;i++){
    if (a == 1 && a == 2 && a == 3){
      console.log("after " + (i+1) + " trials, it becomes true finally!!!");
      break;
    }
  }
}

ocomfd
quelle
102
Ich würde diese Antwort absichtlich geben, selbst wenn ich die anderen Lösungen kenne, weil sie die Frage beantwortet, aber offensichtlich nicht das ist, wonach sie gesucht haben. Spiele dumme Spiele, gewinne dumme Preise.
ESR
2
Aber was ist, wenn mehr als 1000 Versuche erforderlich sind?
Piyin
9
@Piyin Wenn es mehr als 1000 Versuche dauert, gewinnst du einen Preis!
Skeets
5
Ich mag diese Antwort, weil es extrem ist, dass dies in jeder Sprache möglich ist, wenn die Register / der Cache der CPU mit genügend kosmischen Strahlen getroffen werden, während das Programm ausgeführt wird, oder wenn man absichtlich einen Stromfehler ausführt, so dass der Fehlerzweig von Die if-Bedingung springt nicht wirklich.
Ponkadoodle
Niedrigste: 1, Höchste: 412.
KyleFairns
210

Wenn Sie ohne reguläre Ausdrücke nichts tun können:

var a = {
  r: /\d/g, 
  valueOf: function(){
    return this.r.exec(123)[0]
  }
}

if (a == 1 && a == 2 && a == 3) {
    console.log("!")
}

Dies funktioniert aufgrund einer benutzerdefinierten valueOfMethode, die aufgerufen wird, wenn Object mit primitiv verglichen wird (z. B. Number). Der Haupttrick besteht darin, dass a.valueOfjedes Mal ein neuer Wert zurückgegeben wird, da ein execregulärer Ausdruck mit gFlag aufgerufen wird, wodurch lastIndexdieser reguläre Ausdruck jedes Mal aktualisiert wird , wenn eine Übereinstimmung gefunden wird. Beim ersten Mal this.r.lastIndex == 0stimmt es überein 1und wird aktualisiert lastIndex: Beim this.r.lastIndex == 1nächsten Mal stimmt der reguläre Ausdruck überein 2und so weiter.

Kos
quelle
22
@Abdillah Ein Regex-Objekt merkt sich den letzten Index, mit dem es übereinstimmt. Ein execerneuter Aufruf beginnt mit der Suche von diesem Index aus. MDN ist nicht sehr klar.
Simon Chan
Ich this.rverstehe , also erinnert sich das Regex-Objekt an den Status / Index. Vielen Dank!
Abdillah
Ich würde jedoch empfehlen, eine Zeichenfolge zu übergeben exec, nicht eine zu stringifizierende Ganzzahl.
Bergi
Verwenden Sie Regex und jetzt haben Sie zwei Probleme
Aleksey Solovey
191

Dies kann im globalen Bereich wie folgt erreicht werden. Zur nodejsVerwendung globalanstelle des folgenden windowCodes.

var val = 0;
Object.defineProperty(window, 'a', {
  get: function() {
    return ++val;
  }
});
if (a == 1 && a == 2 && a == 3) {
  console.log('yay');
}

Diese Antwort missbraucht die impliziten Variablen, die vom globalen Bereich im Ausführungskontext bereitgestellt werden, indem ein Getter zum Abrufen der Variablen definiert wird.

jontro
quelle
Dies setzt voraus, dass aes sich um eine Eigenschaft handelt, thisdie es nicht zu sein scheint. Wenn aes sich um eine lokale Variable handelt (wie sie aussieht), würde dies nicht funktionieren.
jfriend00
1
@ jfriend00 du meinst wenn du var a platziert hast; irgendwo?
Jontro
Ja. Referenzieren a == 1impliziert, dass aes sich irgendwo um eine Variable handelt, nicht um eine Eigenschaft von this. Während es einen seltsamen Ort wie Globals gibt, an dem beides wahr sein könnte, bedeutet das Deklarieren einer Variablen mit var aoder let abedeutet, dass es keine gibt this, auf die Sie aals Eigenschaft zugreifen können, wie Sie es von Code annehmen. Ihr Code geht also anscheinend von einer seltsamen globalen Variablen aus. Beispielsweise funktioniert Ihr Code nicht in node.js und nicht im strengen Modus innerhalb einer Funktion. Sie sollten die genauen Umstände angeben, unter denen es funktioniert, und wahrscheinlich erklären, warum es funktioniert. Ansonsten ist es irreführend.
jfriend00
@ jfriend00 gut sicher. Ich bin mir nicht sicher, ob es in Kombination mit den anderen bereits Antworten viel mehr Wert hinzufügen würde. Wird die Antwort aktualisieren
jontro
14
Die Frage war, ob dies "jemals" wahr sein könnte. Die Antwort lautet "Ja", und dies ist eines der Szenarien, in denen dies möglicherweise zutrifft: Es ahandelt sich nicht um eine lokale Variable und wird im globalen Bereich mit einem inkrementierenden Getter definiert.
Zac Delventhal
190

Dies ist möglich, wenn auf Variablen avon beispielsweise 2 Web-Workern über einen SharedArrayBuffer sowie ein Hauptskript zugegriffen wird. Die Möglichkeit ist gering, aber es ist möglich , dass , wenn der Code in Maschinencode kompiliert wird, die Web - Arbeiter die Variable aktualisieren , aso dass die Bedingungen gerade rechtzeitig a==1, a==2und a==3sind zufrieden.

Dies kann ein Beispiel für die Race-Bedingung in einer Multithread-Umgebung sein, die von Web-Workern und SharedArrayBuffer in JavaScript bereitgestellt wird.

Hier ist die grundlegende Implementierung von oben:

main.js

// Main Thread

const worker = new Worker('worker.js')
const modifiers = [new Worker('modifier.js'), new Worker('modifier.js')] // Let's use 2 workers
const sab = new SharedArrayBuffer(1)

modifiers.forEach(m => m.postMessage(sab))
worker.postMessage(sab)

worker.js

let array

Object.defineProperty(self, 'a', {
  get() {
    return array[0]
  }
});

addEventListener('message', ({data}) => {
    array = new Uint8Array(data)
    let count = 0
    do {
        var res = a == 1 && a == 2 && a == 3
        ++count
    } while(res == false) // just for clarity. !res is fine
    console.log(`It happened after ${count} iterations`)
    console.log('You should\'ve never seen this')
})

modifier.js

addEventListener('message' , ({data}) => {
    setInterval( () => {
        new Uint8Array(data)[0] = Math.floor(Math.random()*3) + 1
    })
})

Auf meinem MacBook Air geschieht dies nach ungefähr 10 Milliarden Iterationen beim ersten Versuch:

Geben Sie hier die Bildbeschreibung ein

Zweiter Versuch:

Geben Sie hier die Bildbeschreibung ein

Wie gesagt, die Chancen werden gering sein, aber wenn genügend Zeit zur Verfügung steht, wird es die Bedingung treffen.

Tipp: Wenn es auf Ihrem System zu lange dauert. Versuchen Sie es nur a == 1 && a == 2und wechseln Sie Math.random()*3zu Math.random()*2. Wenn Sie mehr und mehr zur Liste hinzufügen, verringert sich die Trefferchance.

mehulmpt
quelle
50
Ehrlich gesagt ist dies die beste Antwort. Alle anderen Antworten erfordern einen absichtlichen Versuch, etwas zutiefst Unintuitives zu tun. Diese Antwort spiegelt tatsächlich etwas wider, das in der realen Welt passieren könnte - eine Rennbedingung.
Tom Swirly
34
Nicht nur das - ich habe dies tatsächlich in der realen Welt gesehen. Nicht mit der genauen Bedingung in der Frage, aber sicherlich mit der Überprüfung von (a == 1) zu Beginn einer Funktion und (a == 2) später in der Funktion und dem Erreichen beider Bedingungen durch Code. Zu Ihrer Information, das erste Mal, dass ich dies sah, war in einem Automotor-Controller, und wir haben Codierungsstandards eingeführt. Das zweite Mal war in einem Spreu- und Fackelspendersystem für Militärflugzeuge, und an meinem ersten Tag in der Firma fand ich dies und reparierte es, während der Rest des Teams noch über das Problem diskutierte. (Kudos Level: hoch! :)
Graham
38
Sie haben also an "Automotorsteuerungen" und "Spreu- und Fackelspendersystemen" gearbeitet, die mit Webarbeitern in Javascript programmiert sind? Ich glaube nicht, dass ich wieder nach draußen gehen werde.
Psaxton
12
@psaxton :) Natürlich nicht - aber wir haben Multithread-Software mit gemeinsam genutzten Daten. Dies ist ein Anti-Pattern für alle Multithread-Software, nicht spezifisch für Javascript oder Web-Worker. Es spielt keine Rolle, ob Sie in Assemblersprache, Brainf * ck, Visual BASIC, C oder Javascript programmieren. Wenn Sie dies mit gemeinsam genutzten Daten in einer Multithread-Anwendung tun, schlägt dies immer fehl.
Graham
4
Ich denke, dies ist jetzt eine ausführliche Zusammenfassung der Antwort von @ jontro.
Qntm
148

Dies ist auch mit einer Reihe von selbst überschreibenden Gettern möglich:

(Dies ähnelt der Lösung von jontro, erfordert jedoch keine Zählervariable.)

(() => {
    "use strict";
    Object.defineProperty(this, "a", {
        "get": () => {
            Object.defineProperty(this, "a", {
                "get": () => {
                    Object.defineProperty(this, "a", {
                        "get": () => {
                            return 3;
                        }
                    });
                    return 2;
                },
                configurable: true
            });
            return 1;
        },
        configurable: true
    });
    if (a == 1 && a == 2 && a == 3) {
        document.body.append("Yes, it’s possible.");
    }
})();

Patrick Dark
quelle
61
Beachten Sie, dass der Ansatz der Verwendung eines Getters ===nicht nur funktioniert ==.
Makyen
Diese Lösung basiert darauf this, das globale Objekt innerhalb des Körpers der Pfeilfunktion zu sein.
Roy Tinker
@Midnightas Ich würde keine anderen Antworten als "Pyramidencode" kategorisieren .
Patrick Roberts
Beachten Sie, dass dies auch mit beliebiger Reihenfolge funktioniert, nicht wahr? Wie (a == 3 && a == 2 && a == 1)?
Johannes
131

Alternativ können Sie eine Klasse dafür und eine Instanz für die Prüfung verwenden.

function A() {
    var value = 0;
    this.valueOf = function () { return ++value; };
}

var a = new A;

if (a == 1 && a == 2 && a == 3) {
    console.log('bingo!');
}

BEARBEITEN

Mit ES6-Klassen würde es so aussehen

class A {
  constructor() {
    this.value = 0;
    this.valueOf();
  }
  valueOf() {
    return this.value++;
  };
}

let a = new A;

if (a == 1 && a == 2 && a == 3) {
  console.log('bingo!');
}

Nina Scholz
quelle
5
gerade function A() {value = 0;am Anfang?
Dave C
valueOfwird überschrieben, this method is usually called automatically by JavaScript behind the scenes, and not explicitly in codealso wenn wir den Wert vergleichen, erhöht er tatsächlich a ..
Danyal Sandeelo
130

Ich sehe diese Antwort nicht bereits gepostet, also werde ich diese auch in die Mischung werfen. Dies ähnelt Jeffs Antwort mit dem Hangul-Raum halber Breite.

var a = 1;
var  = 2;
var а = 3;
if(a == 1 &&  == 2 && а == 3) {
    console.log("Why hello there!")
}

Möglicherweise stellen Sie eine leichte Abweichung von der zweiten fest, aber die erste und dritte sind mit dem bloßen Auge identisch. Alle 3 sind unterschiedliche Zeichen:

a- Lateinische Kleinbuchstaben A
- Volle Breite Lateinische Kleinbuchstaben A
а- Kyrillische Kleinbuchstaben A.

Der Oberbegriff dafür ist "Homoglyphen": verschiedene Unicode-Zeichen, die gleich aussehen. Normalerweise ist es schwierig, drei zu bekommen , die absolut nicht zu unterscheiden sind, aber in einigen Fällen kann man Glück haben. A, Α, А und Ꭺ würde besser funktionieren (Latein-A, griechisches Alpha , Kyrillisch-A und Cherokee-A verbunden sind; leider die griechische und Cherokee Kleinbuchstaben sind zu verschieden von dem lateinischen a: α, und so doesn Ich helfe nicht mit dem obigen Ausschnitt.

Es gibt eine ganze Klasse von Homoglyphenangriffen, am häufigsten in gefälschten Domainnamen (z. B. wikipediа.org(kyrillisch) vs wikipedia.org(lateinisch)), aber sie können auch im Code angezeigt werden . Wird normalerweise als hinterhältig bezeichnet (wie in einem Kommentar erwähnt, sind [hinterhältige] Fragen bei PPCG nicht mehr aktuell , waren jedoch früher eine Art Herausforderung, bei der sich solche Dinge zeigten). Ich habe diese Website verwendet , um die für diese Antwort verwendeten Homoglyphen zu finden.

Draco18s vertraut SE nicht mehr
quelle
19
"Leichte Diskrepanz" würde ich nicht so nennen.
4
@hvd Hängt ganz von Ihrer Schriftwiedergabe ab. Das sehe ich .
Draco18s vertraut SE am
1
@ Jake Ja, das lateinische Kleinbuchstaben A in voller Breite ist nicht die größte Homoglyphe (aber die Großbuchstabenvarianten sind erstaunlich). Im Allgemeinen benötigen Sie jedoch nur zwei, um den gewünschten Effekt zu erzielen.
Draco18s vertraut SE am
@ Draco18s Einverstanden bezüglich: Normalerweise werden nur 2 benötigt. Gute Arbeit bei den zusätzlichen Informationen!
JakeSteam
10
Sie können auch den Unicode-Varianten-Selektor (U + FE00..U + FE0F) verwenden. Keines davon ist a: a︀ a︁ a︂. Machen Sie sich keine Sorgen mehr über Unstimmigkeiten.
Salman A
108

Ja, es ist möglich! 😎

»JavaScript

if‌=()=>!0;
var a = 9;

if‌(a==1 && a== 2 && a==3)
{
    document.write("<h1>Yes, it is possible!😎</h1>")
}

Der obige Code ist eine Kurzversion (danke an @Forivin für den Hinweis in den Kommentaren) und der folgende Code ist original:

var a = 9;

if‌(a==1 && a== 2 && a==3)
{
    //console.log("Yes, it is possible!😎")
    document.write("<h1>Yes, it is possible!😎</h1>")
}

//--------------------------------------------

function if‌(){return true;}

Wenn Sie nur die Oberseite meines Codes sehen und ihn ausführen, sagen Sie WOW, wie?

Ich denke, es reicht aus, Ja zu sagen , es ist jemandem möglich , der zu Ihnen gesagt hat: Nichts ist unmöglich

Trick: Ich habe danach ein verstecktes Zeichen verwendet if, um eine Funktion zu erstellen, deren Name ähnlich ist if. In JavaScript können wir Schlüsselwörter nicht überschreiben, daher musste ich diese Methode verwenden. Es ist eine Fälschung if, aber es funktioniert in diesem Fall für Sie!


» C #

Außerdem habe ich eine C # -Version geschrieben ( mit Technik zur Erhöhung des Eigenschaftswerts ):

static int _a;
public static int a => ++_a;

public static void Main()
{
    if(a==1 && a==2 && a==3)
    {
        Console.WriteLine("Yes, it is possible!😎");
    }
}

Live-Demo

RAM
quelle
56
Die Javascript-Version ist ein echtes Verbrechen gegen die Menschlichkeit und die Fähigkeit, dies zu tun, sollte nach UN-Konventionen illegal sein. Ich denke, es ist an der Zeit, die Welt von allem Wissen über Javacript zu befreien.
Klarer
2
Die Funktionsdeklaration könnte noch kürzer sein. if‌=()=>!0
Forivin
4
Warum um alles in der Welt hast du benutzt document.write? Das ist ein todsicherer Weg, um unabhängig vom Rest der Antwort nicht eingestellt zu werden.
Cerbrus
3
@ Cerbrus, vielen Dank für Ihre Nachricht. Ich habe zuerst meine Antwort mit geschrieben, console.logaber ich habe sie in document.write geändert. Wirklich immer verwende ich console.login meinen Codes, aber hier möchte ich den Benutzern nur einen Text im StackOverflow-Code-Snippet-Feld anzeigen. Deshalb wollte ich meine Nachricht schöner zeigen als die von console.log. Klicken Sie auf die Run Code SnippetSchaltfläche in meiner Antwort und auf andere Antworten. Mit dem SO-Code-Snippet konnte ich HTML, JS und CSS verwenden, dann wollte ich es in meiner Antwort verwenden und es schön machen. Ich denke, es hat keine negativen Nebenwirkungen und hat meine Antwort nicht groß oder vollständig gemacht.
RAM
1
@Clearer, Wenn UN-Konventionen die Welt effektiv verändern könnten, dann sollten wir eine bessere Welt als diese haben. Wir brauchen etwas mehr als eine Erklärung in der UNO und bis zu diesem Tag denke ich, dass wir diesen Javascript-Trick von mir verwenden können;)
RAM
97

JavaScript

a == a +1

In JavaScript gibt es keine Ganzzahlen, sondern nur Numbers, die als Gleitkommazahlen mit doppelter Genauigkeit implementiert sind.

Dies bedeutet, dass eine Zahl, adie groß genug ist, als gleich drei aufeinanderfolgende Ganzzahlen betrachtet werden kann:

a = 100000000000000000
if (a == a+1 && a == a+2 && a == a+3){
  console.log("Precision loss!");
}

Es ist zwar nicht genau das, was der Interviewer gefragt hat (es funktioniert nicht damit a=0), aber es beinhaltet keinen Trick mit versteckten Funktionen oder Überlastung des Bedieners.

Andere Sprachen

Als Referenz gibt es a==1 && a==2 && a==3Lösungen in Ruby und Python. Mit einer geringfügigen Änderung ist dies auch in Java möglich.

Rubin

Mit einem Brauch ==:

class A
  def ==(o)
    true
  end
end

a = A.new

if a == 1 && a == 2 && a == 3
  puts "Don't do this!"
end

Oder eine zunehmende a:

def a
  @a ||= 0
  @a += 1
end

if a == 1 && a == 2 && a == 3
  puts "Don't do this!"
end

Python

class A:
    def __eq__(self, who_cares):
        return True
a = A()

if a == 1 and a == 2 and a == 3:
    print("Don't do that!")

Java

Es ist möglich, den Java- IntegerCache zu ändern :

package stackoverflow;

import java.lang.reflect.Field;

public class IntegerMess
{
    public static void main(String[] args) throws Exception {
        Field valueField = Integer.class.getDeclaredField("value");
        valueField.setAccessible(true);
        valueField.setInt(1, valueField.getInt(42));
        valueField.setInt(2, valueField.getInt(42));
        valueField.setInt(3, valueField.getInt(42));
        valueField.setAccessible(false);

        Integer a = 42;

        if (a.equals(1) && a.equals(2) && a.equals(3)) {
            System.out.println("Bad idea.");
        }
    }
}
Eric Duminil
quelle
27
@ cᴏʟᴅsᴘᴇᴇᴅ: Java, Javascript, Potayto, Potahto :) Es gibt bereits genug gute JS-Antworten. Ich dachte nur, es wäre interessant zu zeigen, wie es in anderen Sprachen gemacht werden kann, und möglicherweise JS-Entwicklern einige Ideen zu geben.
Eric Duminil
2
@ cᴏʟᴅsᴘᴇᴇᴅ: Aktualisiert mit einem JS-Beispiel.
Eric Duminil
1
Warum funktioniert die Java-Version nicht mit Integer a = 42(oder funktioniert es)? Soweit ich Autoboxing verstehe, Integer a = 42; a == 1 && a == 2 && a == 3sollten alle Ints verpackt werden. Oder entpackt dies eine für die Vergleiche?
CAD97
@ CAD97: Integer == intscheint zu Unboxing zu führen. Aber mit Integer#equals(int)Force Autoboxing, so funktioniert es. Danke für den Kommentar!
Eric Duminil
@StephanBijzitter: Bitte erklären Sie. Soweit ich weiß, gibt es nur Numbersin JS, die im Grunde wie doubles sind. Sie können wie Ganzzahlen aussehen und Sie können sie wie Ganzzahlen verwenden, aber sie sind immer noch keine Ganzzahlen. Ich glaube nicht, dass n == n + 1dies jemals für ganze Zahlen in Java / Python / C / Ruby / ... zutreffen kann
Eric Duminil
80

Dies ist eine invertierte Version von @ Jeffs Antwort * wo ein verstecktes Zeichen (U + 115F, U + 1160 oder U + 3164) verwendet wird , Variablen zu erstellen , die aussehen wie 1, 2und 3.

var  a = 1;
var 1 = a;
var 2 = a;
var 3 = a;
console.log( a ==ᅠ1 && a ==ᅠ2 && a ==ᅠ3 );

* Diese Antwort kann vereinfacht werden, indem ein Nicht-Joiner mit Nullbreite (U + 200C) und ein Joiner mit Nullbreite (U + 200D) verwendet werden. Diese beiden Zeichen sind in Bezeichnern zulässig, jedoch nicht am Anfang:

var a = 1;
var a = 2;
var a = 3;
console.log(a == 1 && a == 2 && a == 3);

/****
var a = 1;
var a\u200c = 2;
var a\u200d = 3;
console.log(a == 1 && a\u200c == 2 && a\u200d == 3);
****/

Andere Tricks sind mit derselben Idee möglich, z. B. mithilfe von Unicode-Variationsselektoren, um Variablen zu erstellen, die genau gleich aussehen ( a︀ = 1; a︁ = 2; a︀ == 1 && a︁ == 2; // true).

Salman A.
quelle
75

Regel Nummer eins der Interviews; Sag niemals unmöglich.

Keine Notwendigkeit für Tricks mit versteckten Charakteren.

window.__defineGetter__( 'a', function(){
    if( typeof i !== 'number' ){
        // define i in the global namespace so that it's not lost after this function runs
        i = 0;
    }
    return ++i;
});

if( a == 1 && a == 2 && a == 3 ){
    alert( 'Oh dear, what have we done?' );
}

MonkeyZeus
quelle
6
Autsch. __defineGetter__ist eigentlich nicht Teil der js-Sprache, nur eine hässliche Version von defineProperty. typeofist keine Funktion und diese nicht deklarierte iist einfach schrecklich. Scheint immer noch 40 Upvotes wert zu sein: /
Jonas Wilms
6
@ JonasW. 41 Upvotes :-) Ich bin mir bewusst, dass dies __defineGetter__pro Entwickler nicht mehr empfohlen wird defineProperty()weil Legacy-Code echt ist und nicht ignoriert werden kann. Unabhängig von der Hässlichkeit iist es ein bekanntes / dokumentiertes Verhalten , so zu erklären, wie ich es getan habe. Vielleicht war ich nur in einer PCG-Stimmung ¯ \ _ (ツ) _ / ¯
MonkeyZeus
68

Ehrlich gesagt, ob es eine Möglichkeit gibt, sie als wahr zu bewerten oder nicht (und wie andere gezeigt haben, gibt es mehrere Möglichkeiten), wäre die Antwort, nach der ich suchen würde, wenn ich als jemand spreche, der Hunderte von Interviews geführt hat etwas in der Art von:

"Nun, vielleicht ja unter einigen seltsamen Umständen, die mir nicht sofort klar sind ... aber wenn ich dies in echtem Code antreffen würde, würde ich gängige Debugging-Techniken verwenden, um herauszufinden, wie und warum es das tat, was es tat und dann den Code sofort umgestalten, um diese Situation zu vermeiden ... aber was noch wichtiger ist: Ich würde diesen Code NIEMALS schreiben, da dies genau die Definition von verschlungenem Code ist und ich mich bemühe, niemals verschlungenen Code zu schreiben. "

Ich denke, einige Interviewer würden es beleidigen, wenn eine offensichtlich sehr knifflige Frage gestellt wird, aber es macht mir nichts aus, wenn Entwickler eine Meinung haben, insbesondere wenn sie diese mit begründeten Gedanken untermauern und meine Frage ineinander greifen können eine aussagekräftige Aussage über sich.

Frank W. Zammetti
quelle
13
Die Frage (oder alle Interviewfragen) besteht wahrscheinlich darin, die Bereitschaft der Kandidaten zu testen, über ein Problem nachzudenken, insbesondere über solche, die "anscheinend offensichtlich" sind, wie dieses. Jemand, der sich weigert zu denken, weil er glaubt, die Antwort zu "kennen", ist keine gute Einstellung.
Shammoo
5
@ Don Hatch Nein, ich würde sie nicht bestrafen, wenn sie in gutem Glauben geantwortet hätten und insbesondere wenn sie eine korrekte Antwort gegeben hätten, wie die anderen gezeigt haben ... aber ich würde dann ein Follow-up bitten, um zu versuchen, zu prüfen, ob sie denken, dass es das ist eine gute Möglichkeit, Code zu schreiben oder nicht. Sachkenntnis und die Fähigkeit, eine "richtige" Antwort zu finden, sind nur ein Teil davon, ein guter Entwickler zu sein. Viel wichtiger für einen "professionellen" Entwickler ist das Schreiben von Code, der später verständlich und wartbar ist, oftmals von weniger fähigen Entwicklern. Übermäßig clevere Entwickler sind genauso schlecht wie unfähige IME.
Frank W. Zammetti
16
Dies beantwortet die Frage nicht.
TylerH
6
Das Traurige an dieser Antwort ist, dass ein 1rep-Benutzer das gestern beantwortet hat und 2 Downvotes erhalten hat, die ihn veranlasst haben, diese Frage zu löschen.
Jonas Wilms
8
@ JohnColeman die Frage fragt, wie der Code als wahr ausgewertet werden könnte. Es wird nicht nach den Gründen gefragt, aus denen der Interviewer die Frage überhaupt vorgeschlagen hat. Diese Antwort versucht nicht einmal, die gestellte Frage zu beantworten, sondern konzentriert sich ausschließlich auf eine "Was ich tun würde" -Version eines Versuchs, den Zweck des Interviewers zu erraten. Wenn das die Frage wäre, wäre sie viel zu weit gefasst. Daher gehört diese Antwort nicht hierher oder irgendwo auf der Website.
TylerH
43

Wenn Sie jemals eine solche Interviewfrage erhalten (oder ein ebenso unerwartetes Verhalten in Ihrem Code bemerken), überlegen Sie, welche Art von Dingen möglicherweise ein Verhalten verursachen können, das auf den ersten Blick unmöglich erscheint:

  1. Codierung : In diesem Fall ist die Variable, die Sie betrachten, nicht die, von der Sie glauben, dass sie es ist. Dies kann passieren, wenn Sie absichtlich mit Unicode herumspielen, indem Sie Homoglyphen oder Leerzeichen verwenden , damit der Name einer Variablen wie eine andere aussieht. Codierungsprobleme können jedoch auch versehentlich auftreten, z. B. beim Kopieren und Einfügen von Code aus dem Web, der unerwarteten Unicode-Code enthält Punkte (z. B. weil ein Content-Management-System einige "automatische Formatierungen" vorgenommen hat, z. B. das Ersetzen fldurch Unicode 'LATIN SMALL LIGATURE FL' (U + FB02)).

  2. Rennbedingungen : Eine Rennbedingung kann auftreten, dh eine Situation, in der Code nicht in der vom Entwickler erwarteten Reihenfolge ausgeführt wird. Race-Bedingungen treten häufig in Multithread-Code auf, aber mehrere Threads sind keine Voraussetzung dafür, dass Race-Bedingungen möglich sind - Asynchronität ist ausreichend (und nicht zu verwechseln, Async bedeutet nicht, dass mehrere Threads unter der Haube verwendet werden ).

    Beachten Sie, dass JavaScript daher auch nicht frei von Rennbedingungen ist, nur weil es Single-Threaded ist. Sehen Sie hier für ein einfaches Single-Threaded - aber Asynchron - Beispiel. Im Kontext einer einzelnen Aussage wäre die Rennbedingung in JavaScript jedoch ziemlich schwer zu treffen.

    JavaScript mit Web-Workern ist etwas anders, da Sie mehrere Threads haben können. @mehulmpt hat uns einen großartigen Proof-of-Concept mit Web- Workern gezeigt .

  3. Nebenwirkungen : Eine Nebenwirkung der Gleichheitsvergleichsoperation (die nicht so offensichtlich sein muss wie in den Beispielen hier, häufig sind Nebenwirkungen sehr subtil).

Diese Art von Fragen können in vielen Programmiersprachen erscheinen, nicht nur JavaScript, so dass wir nicht zu den klassischen Sehen Sie JavaScript WTFs hier 1 .

Natürlich sehen die Interviewfrage und die Beispiele hier alle sehr ausgefeilt aus. Aber sie sind eine gute Erinnerung daran, dass:

  • Nebenwirkungen können sehr schlimm werden und ein gut gestaltetes Programm sollte frei von unerwünschten Nebenwirkungen sein.
  • Multithreading und veränderlicher Zustand können problematisch sein.
  • Wenn die Zeichencodierung und Zeichenfolgenverarbeitung nicht richtig ausgeführt wird, kann dies zu bösen Fehlern führen.

1 Zum Beispiel können Sie ein Beispiel in einer völlig anderen Programmiersprache (C #) aufweist , eine Nebenwirkung (eine der nahe liegenden) finden sich hier .

Dirk Vollmar
quelle
1
Dann wird die Frage viel zu weit gefasst. Verschiedene Sprachen können dies mit unterschiedlicher Leichtigkeit implementieren. Die Frage hat so viel Anklang gefunden, weil es sich um eine JS-spezifische Frage und Antwort handelt, aber das ist nur meine 2c.
CS95
1
Die Ursachen sind unterschiedliche C # und Javascript, daher ist diese Antwort nicht legitim.
Edwin
3
@Edwin: Die Ursachen sind genau die gleichen: Unicode-Fummelei mit ähnlich aussehenden Glyphen oder Leerzeichen, Rassenbedingungen oder Nebenwirkungen der Vergleichsoperation (letztere wird in meinem Beispiel gezeigt).
Dirk Vollmar
2
@ cᴏʟᴅsᴘᴇᴇᴅ: Manchmal hilft es, Dinge aus einem breiteren Blickwinkel zu betrachten, um das eigentliche Problem zu erkennen.
Dirk Vollmar
3
Ich wünschte, diese Antwort könnte auf eine "Meta" -Methode mit dieser Frage versehen werden. Nachdem ich alle Antworten darüber gelesen hatte, hatte ich das Gefühl, dass JS so viele Löcher hat, aber Sie haben einfach alle Antworten auf einmal zusammengefasst. Und Sie haben es so gemacht, dass dies meiner Meinung nach zu einer herausragenden Interviewfrage wird (wenn das sprachspezifische Tag entfernt wird). Bravo!
KCE
41

Hier ist eine weitere Variante, bei der mithilfe eines Arrays beliebige Werte angezeigt werden.

const a = {
  n: [3,2,1],
  toString: function () {
    return a.n.pop();
  }
}

if(a == 1 && a == 2 && a == 3) {
  console.log('Yes');
}

Théophile
quelle
31

Okay, noch ein Hack mit Generatoren:

const value = function* () {
  let i = 0;
  while(true) yield ++i;
}();

Object.defineProperty(this, 'a', {
  get() {
    return value.next().value;
  }
});

if (a === 1 && a === 2 && a === 3) {
  console.log('yo!');
}

BaggersIO
quelle
Sie sagen Hack, aber ich bin mir ziemlich sicher, dass dies der Anwendungsfall von Generatoren ist ... :) (naja, außer dass dies davon abhängt this, das Fensterobjekt zu sein)
Cody G
29

Mit Proxies :

var a = new Proxy({ i: 0 }, {
    get: (target, name) => name === Symbol.toPrimitive ? () => ++target.i : target[name],
});
console.log(a == 1 && a == 2 && a == 3);

Proxies geben im Grunde genommen vor, ein Zielobjekt zu sein (der erste Parameter), fangen jedoch Operationen am Zielobjekt ab (in diesem Fall die Operation "get property"), sodass die Möglichkeit besteht, etwas anderes als das Standardobjektverhalten auszuführen. In diesem Fall wird die Aktion "get property" aufgerufen, awenn ==der Typ erzwungen wird, um ihn mit jeder Zahl zu vergleichen. Das passiert:

  1. Wir erstellen ein Zielobjekt, { i: 0 }in dem die iEigenschaft unser Zähler ist
  2. Wir erstellen einen Proxy für das Zielobjekt und weisen ihn zu a
  3. Für jeden a ==Vergleich wird ader Typ auf einen primitiven Wert gezwungen
  4. Diese Art von Zwang führt zu einem a[Symbol.toPrimitive]()internen Anruf
  5. Der Proxy fängt ab, die a[Symbol.toPrimitive]Funktion mit dem "get handler" abzurufen.
  6. Der "get handler" des Proxys prüft, ob die Eigenschaft abgerufen wird Symbol.toPrimitive. In diesem Fall erhöht er den Zähler und gibt ihn vom Zielobjekt zurück : ++target.i. Wenn eine andere Eigenschaft abgerufen wird, wird einfach auf den Standardeigenschaftswert zurückgegriffen.target[name]

Damit:

var a = ...; // a.valueOf == target.i == 0
a == 1 && // a == ++target.i == 1
a == 2 && // a == ++target.i == 2
a == 3    // a == ++target.i == 3

Wie bei den meisten anderen Antworten funktioniert dies nur mit einer losen Gleichheitsprüfung ( ==), da strenge Gleichheitsprüfungen ( ===) keinen Typzwang ausüben, den der Proxy abfangen kann.

IceCreamYou
quelle
2
Es macht jedoch keinen Sinn, dafür einen Proxy zu verwenden - Symbol.toPrimitivedie gleiche Definition für ein Objekt würde genauso gut funktionieren.
Ry-
27

Tatsächlich lautet die Antwort auf den ersten Teil der Frage in jeder Programmiersprache "Ja". Dies ist beispielsweise bei C / C ++ der Fall:

#define a   (b++)
int b = 1;
if (a ==1 && a== 2 && a==3) {
    std::cout << "Yes, it's possible!" << std::endl;
} else {
    std::cout << "it's impossible!" << std::endl;
}
Gustavo Rodríguez
quelle
27
Ich denke nicht, dass es in jeder Programmiersprache möglich ist. Beispielsweise haben nicht alle Sprachen Präprozessoren. Im Übrigen werden nicht alle Sprachen &&für logisches "und" verwendet.
Keith Thompson
3
Ich habe einen Weg gefunden, der sowohl in Python als auch in C ++ funktioniert und Operatorüberladung verwendet.
Donald Duck
7
Und Sie können dies in Java tun, indem Sie Reflection verwenden und den Integer-Cache durcheinander bringen.
CAD97
7
Kann es nicht in Sprachen tun, die eine Mutation an dieser Stelle nicht unterstützen würden, z. B. ist nichts Vergleichbares in haskell verfügbar
Jason Carr
4
Die Frage bezieht sich auf JavaScript, nicht auf C ++.
Alle Arbeiter sind wesentlich
26

Gleich, aber unterschiedlich, aber immer noch gleich (kann mehrfach "getestet" werden):

const a = { valueOf: () => this.n = (this.n || 0) % 3 + 1}
    
if(a == 1 && a == 2 && a == 3) {
  console.log('Hello World!');
}

if(a == 1 && a == 2 && a == 3) {
  console.log('Hello World!');
}

Meine Idee begann damit, wie die Gleichung des Zahlenobjekttyps funktioniert.

Preda7or
quelle
4
Funktioniert auch zum zweiten Mal!
Salman A
25

Eine ECMAScript 6-Antwort, die Symbole verwendet:

const a = {value: 1};
a[Symbol.toPrimitive] = function() { return this.value++ };
console.log((a == 1 && a == 2 && a == 3));

Durch ==Nutzung wird JavaScript soll coerce ain etwas nahe dem zweiten Operanden ( 1, 2, 3in diesem Fall). Bevor JavaScript jedoch versucht, das Erzwingen selbst zu ermitteln, wird versucht, es aufzurufen Symbol.toPrimitive. Wenn Sie Symbol.toPrimitiveJavaScript bereitstellen , wird der Wert verwendet, den Ihre Funktion zurückgibt. Wenn nicht, würde JavaScript aufrufen valueOf.

Omar Alshaker
quelle
24

Ich denke, dies ist der minimale Code, um es zu implementieren:

i=0,a={valueOf:()=>++i}

if (a == 1 && a == 2 && a == 3) {
  console.log('Mind === Blown');
}

Erstellen eines Dummy-Objekts mit einem benutzerdefinierten Objekt, das bei jedem Aufruf valueOfeine globale Variable erhöht i. 23 Zeichen!

Gafi
quelle
14

Dieser verwendet die defineProperty mit einem netten Nebeneffekt, der eine globale Variable verursacht!

var _a = 1

Object.defineProperty(this, "a", {
  "get": () => {
    return _a++;
  },
  configurable: true
});

console.log(a)
console.log(a)
console.log(a)

Ben Aubin
quelle
8
Sie könnten einen Abschluss über verwenden a: get: (a => () => ++a)(0),kein globales notwendig.
Nina Scholz
13
@NinaScholz sicher, aber wir sprechen hier über schlechte Praktiken - lassen Sie mich nur diese haben: D
Ben Aubin
1

Durch Überschreiben valueOfeiner Klassendeklaration kann Folgendes erreicht werden:

class Thing {
    constructor() {
        this.value = 1;
    }

    valueOf() {
        return this.value++;
    }
}

const a = new Thing();

if(a == 1 && a == 2 && a == 3) {
    console.log(a);
}

Was passiert, ist, dass valueOfin jedem Vergleichsoperator aufgerufen wird. Auf dem ersten awird gleich sein 1, auf dem zweiten awird gleich sein 2, und so weiter und so fort, weil jedes Mal valueOf, wenn aufgerufen wird, der Wert von aerhöht wird.

Daher wird die console.log ausgelöst und ausgegeben (jedenfalls in meinem Terminal) Thing: { value: 4}, was darauf hinweist , dass die Bedingung wahr ist.

Jonathan Kuhl
quelle