JavaScript ist, wenn schon standardmäßig, eine der beliebtesten verfügbaren Programmiersprachen. Im Laufe der Jahre wurde es als Albtraum bezeichnet, mit dem man arbeiten kann, und in gewissem Maße ist dies wahr! Meistens sagen die Leute jedoch, dass die DOM-API ein Alptraum ist. Trotzdem gibt es eine Handvoll platter Fehler in der Sprache.
Ich möchte anmerken, dass ich JavaScript liebe. Dieser Artikel ist nur für etwas Spaß gedacht und für uns, um einige der Nachteile zu kennen.
Bei der Namenswahl beginnen wir mit einem lustigen Jab. Während es ursprünglich Mocha und dann LiveScript genannt wurde, wurde es später in JavaScript geändert. Der Geschichte zufolge waren die Ähnlichkeiten mit dem Namen Java das Ergebnis einer Zusammenarbeit zwischen Netscape und Sun, im Gegenzug für Netscape, das die Java-Laufzeitumgebung in ihrem beliebten Browser bündelte. Es wurde auch darauf hingewiesen, dass der Name aufgrund der Rivalität zwischen LiveScript und Java für das Client-seitige Scripting fast wie ein Witz kam.
Trotzdem hat es Tausende von Kommentaren gegeben, die "JavaScript hat nichts mit Java zu tun", in Foren im Web!
Bedenken Sie…
console.log (typeof null); // Objekt
Das macht null Sinn. Wenn null das Fehlen eines Werts ist, wie könnte dann sein Typ "Objekt" sein? Die einfache Antwort ist, dass es sich um einen Fehler handelt, der bis zur ersten Version von JavaScript zurückreicht - einer, die sogar fälschlicherweise auf JScript von Microsoft übertragen wurde.
NaN bezieht sich, wie wir erwarten würden, auf einen Wert, der keine gesetzliche Zahl ist. Das Problem ist, dass NaN nicht gleich alles ist, einschließlich sich selbst.
console.log (NaN === NaN); // falsch
Das sollte falsch sein. Wenn Sie feststellen möchten, ob ein Wert tatsächlich NaN ist, können Sie stattdessen die Funktion isNaN () verwenden.
Aktualisieren: Nach dem Lesen einiger brillanter Kommentare, insbesondere derjenigen, bei denen NaN der Unendlichkeit ähnelt, ist es absolut sinnvoll, dass sich NaN nicht selbst gleich ist. Aber es kann immer noch verwirrend sein. In den Kommentaren finden Sie eine ausführliche Diskussion dazu!
Die Abhängigkeit von globalen Variablen gilt weithin als der schlimmste Teil von JavaScript. Bei einfachen Projekten, ähnlich wie bei den Schnelltipps auf dieser Website, macht es keinen Unterschied. Die eigentliche Last globaler Variablen spielt jedoch eine Rolle, wenn Sie beginnen, auf mehrere Skripts zu verweisen, ohne zu wissen, wie sie erstellt oder benannt werden. Wenn sie den gleichen Namen haben wie eine Ihrer Variablen, wird Ihr Programm eine Art Fehler auslösen.
"Das Problem mit JavaScript ist nicht nur das, was es erlaubt (globale Variablen), es erfordert sie." - Crockford
Okay - das ist nicht die Schuld von JavaScript. Ich habe ein bisschen geschummelt. Es liegt an den Browseranbietern. Allerdings ist die Erkennung von Benutzer-Agent-Strings in JavaScript sehr verbreitet. Daher ist es wichtig zu wissen, womit Sie es zu tun haben. Es gehört wahrscheinlich nicht zu dieser Liste, aber wen interessiert das schon! Es ist gut zu wissen.
Dies ist nicht so sehr ein Fehler wie eine unvermeidliche Entscheidung. Öffnen Sie beispielsweise Safari, greifen Sie auf den Web Inspector zu und protokollieren Sie die Benutzeragentenzeichenfolge in der Konsole.
console.log (navigator.userAgent); // Mozilla / 5.0 (Macintosh; U; Intel Mac OS X 10_5_8; de-de) AppleWebKit / 531.21.8 (KHTML, wie Gecko) Version / 4.0.4 Safari / 531.21.10
Beachten Sie die erste Zeichenfolge: Mozilla / 5.0. Warum sollte Safari es als Mozilla-basierten Browser identifizieren? Obwohl es sich später richtig identifiziert, erklärt das noch nicht, warum sie sich die Mühe machen, Programmierer in die Irre zu führen. Tatsächlich werden Sie feststellen, dass sich die meisten Browser als Mozilla identifizieren. Die Antwort geht ein Jahrzehnt zurück und ist wiederum weniger ein Irrtum und eher ein unvermeidlicher Umstand.
Für diejenigen, die nicht vertraut sind, dient eine Benutzer-Agent-Zeichenfolge dazu, den Browser und seine Version zu identifizieren. Zum Beispiel hatte der erste Browser Mosaic eine Benutzer-Agent-Zeichenfolge, die so aussah:
Mosaic / 0.9 // Name des Browsers / Versionsnummer
Das macht absolut Sinn. Als Netscape auf den Markt kam, behielten sie die Verwendung von Mosaic bei und fügten auch einen Abschnitt mit Verschlüsselungstypen hinzu.
Mozilla / 2.02 [de] (Win95; I) // Browsername / Version / Verschlüsselung
So weit, ist es gut. Die Probleme traten ins Spiel, als - Internet Explorer 3 - veröffentlicht wurde. Denken Sie daran, dass Netscape beim Start der beliebteste verfügbare Browser war. Tatsächlich implementierten viele Server und Programme bereits eine Benutzeragentenerkennung, um Netscape zu identifizieren. Obwohl dies heute ein viel diskutiertes Thema ist, war es damals kein großes Problem. Wenn der IE eine eigene Benutzer-Agent-Zeichenfolge verwendet hätte, hätte dies ungefähr so aussehen können:
MSIE / 3.0 (Win95; U)
Dies hätte sie zu einem großen Nachteil gebracht, weil Netscape bereits von vielen Servern identifiziert wurde. Daher beschlossen die Entwickler, den Browser falsch als Mozilla zu identifizieren und dann einen zusätzlichen Satz von Informationen anzufügen, die ihn als Internet Explorer kennzeichnen.
Mozilla / 2.0 (kompatibel; MSIE 3.0; Windows 95)
Heutzutage ist die Benutzer-Agent-Erkennung eine letzte Anstrengung und wird aus diesem Grund so genau betrachtet. Sie werden feststellen, dass die meisten Browser dem Beispiel von IE gefolgt sind, als sich Mozilla zu identifizieren. Betrachten Sie es als Kettenreaktion.
Ich empfehle Ihnen dringend, Nicholas Zakas "History of the User-Agent String" zu lesen, wenn Sie tiefer einsteigen möchten.
Betrachten Sie den folgenden Code:
// Eine Funktion erstellen, die eine Funktion mit dem Namen gleich Parameter fn aufruft. Funktion foo (fn) if (typeof fn === "Funktion") fn (); // Ein Objekt mit einer Eigenschaft und einer Methode erstellen. var bar = barbar: "Hallo, Welt!", Methode: function () alert (this.barbar); ; bar.methode (); // Alarme Hallo, Welt! foo (bar.methode); // Wenn wir die Funktion foo aufrufen, geben Sie die Methode "bar.method" weiter, und es wird "undefined" angezeigt. foo (function () bar.method ();); // Warnungen Hallo, Welt, danach
Der Grund, warum foo (bar.method) nicht dasselbe Ergebnis liefert, liegt darin, dass die Methodenfunktion als Methode des Fensterobjekts und nicht als Leiste aufgerufen wird. Um dies zu beheben, müssen wir bar.method () aus der übergebenen anonymen Funktion aufrufen.
Vielen Dank an Jeremy McPeak für die Benachrichtigung dieses Fehlers.
JavaScript hat viele Gemeinsamkeiten mit Java - einer davon ist die Menge der bitweisen Operatoren.
Betrachten Sie das erste Element, &; Es ist viel effizienter, den Operator && zu verwenden, da er schneller ist. Dies liegt daran, dass JavaScript nicht dasselbe wie Java ist und keine Ganzzahlen hat. Daher ist ein relativ langer Prozess erforderlich, um den Operanden zu konvertieren, etwas zu tun und ihn dann zurück zu konvertieren.
Deshalb können Sie mit & für "und" und | auskommen für "oder" - obwohl Sie && und || verwenden sollten.
Vielleicht ist dies kein spezifischer Fehler in JavaScript, aber es macht den Lernprozess, besonders für Anfänger, sehr schwierig. Werte wie null, falsch und undefiniert bedeuten fast dasselbe, aber es gibt Unterschiede, die für das Verständnis verwirrend sein können.
Öffnen Sie zum Testen die Konsole in Firefox und suchen Sie den Boolean-Wert der folgenden Elemente.
!!(0); // falsch !! (falsch); // false !! ("); // false !! (null); // false !! (undefined); // false !! (NaN); // false
Bitte beachten Sie, dass alle anderen Werte als wahr interpretiert werden.
Mehr als ein Fehler, so viele falsche Werte sind nur verwirrend!
Okay, okay - ich ärgere mich zu 99% mit der Überschrift oben. JavaScript hat jedoch ein paar kleinere Probleme, wenn Sie mit Dezimalzahlen arbeiten, zum Beispiel Geldgeschäfte. Öffnen Sie beispielsweise Ihre Konsole und loggen Sie ".2 + .4". Wir würden erwarten, dass ".6" angezeigt wird, richtig? Gut tut es und tut nicht!
console.log (.2 + .4); // 0.6000000000000001
Woher? Auf hohem Niveau liegt dies daran, dass JavaScript den IEEE-Standard für die binäre Gleitkomma-Arithmetik verwendet hat. Ich verstehe wahrscheinlich genau wie Sie nicht genau, was das spezifiziert, aber ich weiß nur, dass die Ergebnisse bei Dezimalbrüchen geringfügig von den erwarteten Ergebnissen abweichen können. Denken Sie daran, dass die Ganzzahl-Arithmetik perfekt ist. Dies ist also kein großes Problem.
Wenn es um Ihren Codierstil geht, ist es genau das: dein Stil. Einige Leute ziehen es vor, ihre geschweiften Klammern in derselben Linie wie die Kontrolle zu platzieren, andere ziehen es vor, dass sie von alleine geht.
// geschweifte Klammern rechts return foo: bar; // geschweifte Klammern in der eigenen Zeile return foo: bar;
Abhängig von dem ersten Web-Entwickler-Buch, das wir gelesen haben oder wie unser Lehrer es uns beigebracht hat, ist es absolut akzeptabel, eine der beiden oben genannten Methoden oder eine Kombination aus beiden zu verwenden. Das Problem bei JavaScript ist, dass es nicht Ihre Wahl ist!
Ich habe dieses besondere Beispiel aus einem Vortrag gelernt, den Doug Crockford vor etwa einem Jahr gehalten hat. Betrachten Sie die Rückgabeanweisung von oben. Ob Sie es glauben oder nicht, sie sind NICHT gleich. Glaub mir nicht Probieren Sie es aus. Fügen Sie der HTML-Seite Folgendes hinzu.
var foo = function () return a: 'b'; (); Alarm (foo.a); // b
Der obige Code erstellt einfach eine Variable namens foo, die dem zurückgegebenen Objekt entspricht. Wenn wir (foo.a) alarmieren, sehen wir erwartungsgemäß ein Benachrichtigungsfeld mit dem Wert 'b'. Nehmen Sie nun einfach die öffnende geschweifte Klammer aus der return-Anweisung und drücken Sie sie wie in der eigenen Zeile nach unten.
return a: 'b';
Wenn Sie es erneut in Ihrem Browser ausführen, erhalten Sie einen Firebug-Fehler, der protokolliert, dass "foo nicht definiert" ist. Was zur Hölle!? :)
Warum macht JavaScript das so? Es ist wegen etwas namens "Semikolon Einfügen". Grundsätzlich versucht JavaScript, unsere fehlerhafte Kodierung zu korrigieren. Wenn Sie beispielsweise den Eindruck haben, dass Sie ein abschließendes Semikolon weggelassen haben, wird es für Sie hinzugefügt. Obwohl dies ursprünglich als Bequemlichkeit gedacht war, insbesondere für neuere JavaScript-Benutzer, ist es tatsächlich eine sehr schlechte Sache, wenn Sie, wie oben gezeigt, keine Kontrolle über Ihren eigenen Code haben.
In unserem Beispiel gibt es keine Möglichkeit festzustellen, warum foo.a "undefined" zurückgibt. Da wir nun die Einfügung von Semikolons kennen, ist es undefiniert, dass JavaScript ein Semikolon am Ende der return-Anweisung hinzufügt.
Rückkehr; // JS fügt dieses Semikolon falsch ein. a: 'b'; // Hier wird auch ein Semikolon hinzugefügt, da es nicht erkennt, dass dies ein Objekt ist. ;
Wenn wir also sofort zurückkehren, hat es keine Ahnung, was die Eigenschaft "a" ist, was zu "undefined" führt.
Wie ich zu Beginn dieses Artikels erwähnte, liebe ich JavaScript und verwende es täglich. Das heißt aber nicht, dass es nicht wirklich schreckliche Fehler in der Sprache gibt. Ich würde gerne Ihre Gedanken in den Kommentaren hören! Danke fürs Lesen. Retweets und Diggs werden immer geschätzt! Vielen Dank an Jeremy McPeak, Doug Crockford, Nicholas Zakas und John Resig: Ich habe bei der Vorbereitung dieses Artikels auf Ihre Tutorials und Bücher verwiesen.