JavaScript, se solo per impostazione predefinita, è uno dei linguaggi di programmazione più popolari disponibili. Nel corso degli anni, è stato etichettato come un incubo con cui lavorare, e, in una certa misura, questo è vero! Tuttavia, il più delle volte, quello che la gente intende dire è che l'API DOM è un incubo. Tuttavia, ci sono una manciata di errori flat-out nella lingua.
Mi piacerebbe prendere nota che adoro JavaScript. Questo articolo è pensato solo per un po 'di divertimento, e per noi essere consapevoli di alcune sue mancanze.
Inizieremo con un jab divertente alla scelta del nome. Mentre era originariamente chiamato Mocha e poi LiveScript, in seguito è stato cambiato in JavaScript. Secondo la cronologia, le sue somiglianze con il nome Java erano il risultato di una collaborazione tra Netscape e Sun, in cambio di Netscape che accorpava il runtime Java all'interno del loro popolare browser. È stato anche notato che il nome è venuto, quasi come uno scherzo, a causa della rivalità tra LiveScript e Java per lo scripting lato client.
Tuttavia, ha provocato migliaia di commenti "JavaScript non ha nulla a che fare con Java" nei forum sul Web!
Considera questo ...
console.log (typeof null); // oggetto
Questo non ha senso. Se null è l'assenza di un valore, allora come potrebbe il suo tipo essere "oggetto?" La semplice risposta è che è un errore flat-out che risale alla prima versione di JavaScript - uno che è stato anche erroneamente trasferito su JScript di Microsoft.
NaN, come ci aspetteremmo, si riferisce a un valore che non è un numero legale. Il problema è che NaN non è uguale a niente ... compreso se stesso.
console.log (NaN === NaN); // falso
Questo dovrebbe essere sbagliato. Invece, se si desidera determinare se un valore è effettivamente NaN, è possibile utilizzare la funzione isNaN ().
Aggiornare: dopo aver letto alcuni dei brillanti commenti, in particolare quelli relativi al NaN che è simile all'infinito, allora ha perfettamente senso che NaN non si eguaglierebbe. Ma può ancora essere confuso. Fare riferimento ai commenti per una discussione approfondita su questo!
La dipendenza dalle variabili globali è ampiamente considerata la parte peggiore di JavaScript. Per i progetti semplici, proprio come i suggerimenti rapidi su questo sito, non fa davvero la differenza. Tuttavia, il vero problema dei globali entra in gioco quando si inizia a fare riferimento a più script, senza alcuna conoscenza di come vengono creati o denominati. Se capita di condividere lo stesso nome di una delle tue variabili, il tuo programma genererà una sorta di errore.
"Il problema con JavaScript non è solo quello che consente loro (variabili globali), ma richiede loro". - Crockford
Bene, questo non è colpa di JavaScript. Ho barato un po '. È a causa dei venditori di browser. Detto questo, il rilevamento delle stringhe degli user-agent è molto comune in JavaScript; quindi è importante sapere con cosa hai a che fare. Probabilmente non appartiene a questa lista, ma a chi importa? Buono a sapersi.
Questo non è tanto un errore quanto una decisione inevitabile. Ad esempio, apri Safari, accedi a Web Inspector e registra la stringa dell'agente utente nella console.
console.log (navigator.userAgent); // Mozilla / 5.0 (Macintosh; U; Intel Mac OS X 10_5_8; it-it) AppleWebKit / 531.21.8 (KHTML, come Gecko) Versione / 4.0.4 Safari / 531.21.10
Nota quella prima stringa di caratteri: Mozilla / 5.0. Perché Safari dovrebbe identificarlo come un browser basato su Mozilla? Sebbene in seguito si identifichi correttamente, ciò non spiega ancora perché si siano presi la briga di ingannare i programmatori. Infatti, scoprirai che la maggior parte dei browser si identifica come Mozilla. La risposta risale a un decennio, ed è, di nuovo, meno un errore, e più una circostanza inevitabile.
Per chi non ha familiarità, una stringa user-agent ha semplicemente lo scopo di identificare il browser e la sua versione. Ad esempio, il primo browser in assoluto, Mosaic, aveva una stringa user-agent che assomigliava così:
Mosaico / 0.9 // nome del browser / numero di versione
Questo ha perfettamente senso. E quando Netscape entrò in scena, mantennero l'uso di Mosaic e aggiunsero anche una sezione di tipo di crittografia.
Mozilla / 2.02 [it] (Win95; I) // nome browser / versione / crittografia
Fin qui tutto bene. I problemi sono entrati in gioco quando, ad attenderlo, è stato rilasciato Internet Explorer 3. Tieni presente che, al momento del lancio, Netscape era il browser più popolare disponibile. In effetti, molti server e programmi implementavano già il rilevamento degli user-agent per identificare Netscape. Anche se questo è un argomento molto dibattuto oggi, a quei tempi, non era un gran problema. Se IE avesse usato la propria stringa user-agent, sarebbe stata simile a questa:
MSIE / 3.0 (Win95; U)
Ciò li avrebbe lasciati in un enorme svantaggio, perché Netscape era già stato identificato da molti server. In quanto tale, gli sviluppatori hanno deciso di identificare erroneamente il browser come Mozilla e quindi aggiungere un ulteriore set di informazioni etichettandolo come Internet Explorer.
Mozilla / 2.0 (compatibile; MSIE 3.0; Windows 95)
Al giorno d'oggi, il rilevamento degli user-agent è un ultimo sforzo, ed è considerato così precisamente per questo motivo. Scoprirai che la maggior parte dei browser ha seguito il ruolo di IE nell'identificarsi come Mozilla. Pensala come una reazione a catena.
Consiglio vivamente di leggere "History of the User-Agent String" di Nicholas Zakas, se desideri approfondire.
Considera il seguente codice:
// Crea una funzione che chiamerà una funzione con il nome uguale al parametro fn. function foo (fn) if (typeof fn === "function") fn (); // Crea un oggetto con una proprietà e un metodo. var bar = barbar: "Hello, World!", metodo: function () alert (this.barbar); ; bar.method (); // Alerts Hello, World! foo (bar.method); // Se chiamiamo la funzione foo, aggiungi il metodo "bar.method", in qualche modo avverte "indefinito". foo (function () bar.method ();); // avvisi Hello, World, after
Il motivo per cui foo (bar.method) non rende lo stesso risultato è perché la funzione metodo sarà chiamata come metodo dell'oggetto window, piuttosto che bar. Per risolvere questo problema, dobbiamo chiamare bar.method () dalla funzione anonima passata.
Grazie mille a Jeremy McPeak per avermi informato di questo errore.
JavaScript condivide molte somiglianze con Java - uno di questi è l'insieme di operatori bit a bit.
Considera il primo elemento, &; sarebbe molto più efficiente usare l'operatore &&, poiché è più veloce. Questo perché JavaScript non è lo stesso di Java e non ha numeri interi. Come tale, è necessario un processo di lunghezza relativamente lunga per convertire l'operando, fare qualcosa con esso e quindi riconvertirlo.
Questo è il motivo per cui puoi farcela usando & per "e", e | per "o" - anche se dovresti usare && e ||.
Forse questo non è specificamente un errore in JavaScript, ma sicuramente rende il processo di apprendimento, specialmente per i principianti, uno difficile. Valori come null, false e indefiniti significano quasi la stessa cosa, ma ci sono differenze che possono essere fonte di confusione per capire.
Per testare, apri la console in Firefox e trova il valore booleano dei seguenti elementi.
!!(0); // false !! (false); // false !! ("); // false !! (null); // false !! (non definito); // false !! (NaN); // false
Si prega di notare che qualsiasi altro valore sarà interpretato come verità.
Più che un errore, questo molti valori falsi è solo fonte di confusione!
Va bene, okay - Sono stuzzicante al 99% con la voce sopra. Ma JavaScript ha alcuni problemi minori quando si lavora con i decimali, ad esempio cose come le transazioni monetarie. Ad esempio, apri la tua console e registra ".2 + .4". Ci aspettiamo che visualizzi ".6", corretto? Bene, e non è così!
console.log (.2 + .4); // 0.6000000000000001
Come mai? Ad un livello elevato, è perché JavaScript ha utilizzato lo standard IEEE per l'aritmetica in virgola mobile binario. Io, probabilmente come te, non capisco esattamente cosa specifica ciò, ma sappi che, quando si ha a che fare con le frazioni decimali, i risultati possono variare leggermente da quanto ci si potrebbe aspettare. Tieni presente che l'aritmetica dei numeri interi è perfetta, quindi questo non è un grosso problema.
Quando si tratta del tuo stile di codifica, è esattamente questo: il tuo stile. Alcune persone preferiscono posizionare le parentesi graffe sulla stessa riga del controllo, altre preferiscono che vada per conto proprio.
// parentesi a destra return foo: bar; // parentesi sulla propria linea return foo: bar;
A seconda del primo libro di sviluppo web che abbiamo letto, o di come il nostro insegnante ci ha insegnato, è perfettamente accettabile utilizzare uno dei metodi sopra descritti, o anche una combinazione dei due. Il problema con JavaScript è che non è una tua scelta!
Ho imparato questo particolare esempio da una conferenza che Doug Crockford ha dato circa un anno fa. Considera la dichiarazione di ritorno dall'alto. Che ci crediate o no, NON SONO uguali. Non mi credi? Prova questo. Aggiungi quanto segue ad alcune pagine HTML.
var foo = function () return a: 'b'; (); alert (foo.a); // b
Il codice sopra crea semplicemente una variabile chiamata foo, che è uguale all'oggetto restituito. Quando avvisiamo (foo.a), noi, come previsto, vediamo una casella di avviso con un valore di "b". Ora, prendi semplicemente quella parentesi graffa aperta, dall'istruzione return, e spingila fino alla sua linea, in questo modo.
return a: 'b';
Se lo esegui di nuovo nel tuo browser, riceverai un errore Firebug, registrando che "foo non è definito". Che diavolo!? :)
Quindi, perché JavaScript lo fa? È a causa di qualcosa chiamato "inserimento di punto e virgola". In sostanza, JavaScript tenterà di correggere la nostra cattiva codifica. Se, ad esempio, si pensa di aver interrotto il punto e virgola di chiusura, verrà aggiunto e aggiunto per te. Anche se inizialmente era pensato per essere una comodità, specialmente per i nuovi JavaScript, in realtà è una cosa molto brutta quando non hai il controllo sul tuo codice, come dimostrato sopra.
Nel nostro esempio, non c'è modo di determinare perché foo.a restituisce "indefinito". Ora che siamo a conoscenza dell'inserimento del punto e virgola, il motivo per cui è indefinito è perché JavaScript aggiungerà un punto e virgola alla fine dell'istruzione return.
ritorno; // JS aggiunge in modo errato questo punto e virgola. a: 'b'; // Aggiungerà anche un punto e virgola, perché non si rende conto che si tratta di un oggetto. ;
Quindi, se torniamo immediatamente, non ha idea di quale sia la proprietà "a", risultando così "indefinita".
Come ho detto all'inizio di questo articolo, adoro JavaScript e lo uso quotidianamente. Ma ciò non significa che non ci siano errori veramente terribili nella lingua. Mi piacerebbe sentire i tuoi pensieri nei commenti! Grazie per aver letto. Retweet e Diggs sono sempre apprezzati! Grazie mille a Jeremy McPeak, Doug Crockford, Nicholas Zakas e John Resig: mi sono riferito ai tuoi tutorial e ai libri quando preparo questo articolo.