Anmerkung des Moderators: Bitte widerstehen Sie dem Drang, den Code zu bearbeiten oder diesen Hinweis zu entfernen. Das Muster der Leerzeichen kann Teil der Frage sein und sollte daher nicht unnötig manipuliert werden. Wenn Sie der Meinung sind, dass Leerzeichen unbedeutend sind, sollten Sie den Code so akzeptieren können, wie er ist.
Ist es überhaupt möglich, dass (a== 1 && a ==2 && a==3)
in JavaScript als "wahr" ausgewertet werden kann?
Diese Frage wurde mir bei einem Vorstellungsgespräch in einem großen Technologieunternehmen gestellt. Sie wurde vor zwei Wochen gestellt, aber ich versuche immer noch, die Antwort zu finden. Ich weiß, dass wir in unserer täglichen Arbeit nie solchen Code schreiben, aber ich bin neugierig.
Wenn Sie die Vorteile von [how ==
works] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness#Loose_equality_using) nutzen, können Sie einfach ein Objekt mit einer benutzerdefinierten toString
(oder valueOf
) Funktion erstellen, die bei jeder Verwendung die Rückgabe so ändert, dass sie alle drei Bedingungen erfüllt.
const a = {
i: 1,
toString: function () {
return a.i++;
}
}
if(a == 1 && a == 2 && a == 3) {
console.log('Hello World!');
}
Der Grund dafür, dass dies funktioniert, liegt in der Verwendung des losen Gleichheitsoperators. Wenn bei der losen Gleichheit einer der Operanden von einem anderen Typ ist als der andere, versucht die Engine, den einen in den anderen umzuwandeln. Im Falle eines Objekts auf der linken Seite und einer Zahl auf der rechten Seite wird versucht, das Objekt in eine Zahl umzuwandeln, indem zuerst valueOf
aufgerufen wird, wenn es aufrufbar ist, und andernfalls wird toString
aufgerufen. Ich habe in diesem Fall einfach toString
verwendet, weil es das ist, was mir in den Sinn kam, valueOf
würde mehr Sinn machen. Wenn ich stattdessen eine Zeichenkette von "toString" zurückgegeben hätte, hätte die Engine dann versucht, die Zeichenkette in eine Zahl umzuwandeln, was zum gleichen Ergebnis geführt hätte, allerdings mit einem etwas längeren Weg.
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 with
-Anweisung, um a
auf drei verschiedene Werte auszuwerten.
... das bedeutet immer noch nicht, dass dies in echtem Code verwendet werden sollte...
Noch schlimmer ist, dass dieser Trick auch mit der Verwendung von ===
funktionieren wird.
var i = 0;
with({
get a() {
return ++i;
}
}) {
if (a !== a)
console.log("yep, this is printed.");
}
Dies kann mit dem folgenden Code im globalen Bereich erreicht werden. Für nodejs
verwenden Sie global
anstelle von window
im untenstehenden Code.
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 durch den globalen Bereich im Ausführungskontext bereitgestellt werden, indem ein Getter definiert wird, um die Variable abzurufen.