2010-10-13 9 views
22

Quali sono alcuni dei comuni "guai" di Javascript e/o jQuery che hai visto o che sono stati fatti inciampare da?Javascript/jQuery "Gotchas"

A titolo di esempio, è stato fatto notare a me questa mattina che bisogna stare attenti con la radice quando si fa parseInt(), perché se la stringa inizia con un 0, la radice imposterà 8.

+2

Contrassegnare come CW se deve sopravvivere alla chiusura .. –

+1

Decisamente dovrebbe essere CW. – Pointy

+1

Grazie per il/i suggerimento/i. – Ender

risposta

7

i lo consiglierei di leggere tutta la http://wtfjs.com/

+2

sito Nice. Spiega una delle mie domande tra quelle. : P – BrunoLM

+0

la prima domanda riguarda il mio sito e blog! http://www.typeofnan.com: p – jAndy

0

Javascript

parseInt('0aaa') //still returns 0 
parseFloat('0.aaa') //still returns 0 

Questa quelli più di un fattore di oops. Durante la stesura di un'istruzione switch, sono stato conosciuto per dimenticare di inserire un'interruzione nell'istruzione, che causa problemi.

var myvar = '1' 
switch (myvar) { 
    case '1': 
    alert(myvar); 
    case '2': 
    alert(myvar); 
    break; 
} 

perché ho dimenticato la pausa nel case '1' riceverete due volte l'allarme.

+0

l'interruttore non è un 'Jcha/JQUERY' trucchi '. Questo è anche possibile in altre lingue C/C++/C# ecc. – RvdK

+0

@PoweRoy ... lo so ... è esattamente il motivo per cui ho detto che è "più di un fattore oops" –

+0

@PoweRoy: l'angolo di Nitpicker - è un [ errore in fase di compilazione] (http://msdn.microsoft.com/en-us/library/06tc147t.aspx) affinché il controllo ricada attraverso un'etichetta di caso switch in C#. In altre parole, il codice di John non verrebbe compilato se fosse C#. – josh3736

12

Sostituzione .round()/.floor() o .ceil() con ~~ di tagliare posti di distanza decimale è abbastanza bello.

Invece di

Math.floor(Math.random() * 100); 

che fai

~~(Math.random() * 100); 

E 'solo più corta e ha un rendimento migliore, anche!

+1

Questo è più un consiglio/trucco di un trucco, ma comunque molto bello! – Ender

+0

Potrei vedere '.floor()' e '.ceil()' se aggiungete 1, ma non sembra più una sostituzione di '.round()'. Forse questa è la parte * gotcha *? ; o) – user113716

+0

@patrick: beh nel contesto giusto per sbarazzarsi dei decimali, lo è davvero. – jAndy

2

Il libro di Douglas Crockford JavaScript: The Good Parts è un'eccellente lettura sull'argomento. Ci sono anche le parti cattive e terribili di Javascript in esso :)

9

L'ambito di 'questo'

consideri il seguente esempio:

function myClass(message) { 
    this.message = message; 
    $('button').click(function(){ 
    this.onClick(); 
    });  
} 

myClass.prototype.onClick = function() { 
    alert(this.message); 
} 

Naturalmente, la linea 3 non funziona : this funziona su base funzione, e la funzione definita sulla riga 2 avrà il pulsante selezionato come this invece dell'istanza di myClass. C'è una versione ancora sneakier:

function myClass(message) { 
    this.message = message; 
    $('button').click(this.onClick);  
} 

myClass.prototype.onClick = function() { 
    alert(this.message); 
} 

Questa chiama la funzione corretta, ma this sarebbe ancora il pulsante (perché this è determinato dal chiamante, non dal fatto che sei una funzione membro).La soluzione corretta è quella di utilizzare una variabile intermedia, come self, applicare regole di visibilità sane a this:

function myClass(message) { 
    this.message = message; 
    var self = this; 
    $('button').click(function() { self.onClick(); });  
} 

Tipo colata

[] == ![] viene valutato come vero per oscuri motivi

Arrays e Proprietà

Il length proprietà funziona solo per chiavi intere sugli array. Per esempio:

var a = [];  // a.length == 0 
a[0] = 'first'; // a.length == 1 
a['1'] = 'second'; // a.length == 2 
a['x'] = 'third'; // a.length == 2 <-- 'x' does not count 

Mentre su questo argomento, for(in) lavori sugli array, ma traverse tutte proprietà definite sulla matrice. Ciò significa che il tuo codice JavaScript che utilizza lo for(in) per iterare attraverso gli array cesserà improvvisamente di funzionare su determinati browser quando aggiungi ExtJS al tuo progetto, perché ExtJS definisce Array.prototype.filter se non è presente (questo è noto come patch di scimmia). Poiché ora filter è una proprietà personalizzata di ogni oggetto matrice, anche tutti i loop lo eseguono. Boom.

Il modo pulito di iterare attraverso un array consiste nell'utilizzare la lunghezza e un incremento per il ciclo. Oppure jQuery's $.each().

8

Il più grande WTF che ho trovato in Javascript deve essere String.replace.

Prendete questo codice di esempio:

"An,example,of,a,comma,separated,sentence".replace(',', ' '); 

Questo produce una frase ben separati da spazi invece, giusto?

Con mia grande sorpresa: no, non è così. Sostituisce solo la prima virgola con uno spazio, lasciando intatto il resto. Se si desidera eseguire una sostituzione effettiva , è necessario utilizzare .replace(/,/g, ' ').

Perché il metodo non è chiamato "replaceFirst", nessuno lo sa.

+0

in effetti, un malinteso comune (* in realtà deviazione dalla norma *) –

+0

Il trucco è che secondo il documento originale di Netscape che ho, la firma per questo metodo è 'String.replace (regexp, newText)' In molti casi un semplice "Stringa" è usato come primo parametro, quindi il concetto di bandiera globale per la regexp è completamente trascurato. – scunliffe

+1

Quasi tutte le routine di sostituzione delle stringhe che abbia mai visto hanno una modalità "solo il primo" come predefinita. Ad esempio, il comando "vi" replace e tutte le varianti di Unix/Linux come "sed" richiedono un suffisso "g" per fare un "replace all". La libreria Java ha "replace" e "replaceAll", con la stessa semantica (per quanto riguarda comunque la politica di sostituzione). – Pointy

1

Le variabili variabili del ciclo e dell'ambito sono decisamente un "gotcha". Questo succede molto durante l'assegnazione gestori eventi in un ciclo:

var lis= document.getElementsByTagName('li'), 
    imgs = document.getElementsByTagName('img'); 
for (i = 0; i < elements.length; i++) 
{ 
    elements[i].onclick = function() { 
     imgs[i].src = elements[i].innerHTML; 
    } 
} 

Al momento dell'esecuzione, sarà indefinito imgs[i], generare un errore quando si cerca di accedere imgs[i].src. Lo stesso per elements[i] e il suo innerHTML.

+0

Verissimo, ho risposto a una domanda ieri dove questa era la causa del problema. – Ender

1

globali implicite sono una grande:

var x = 12, y = 14; 
function addOne(num) 
{ 
    x = num + 1; // since this is not declared with 'var', it is implied global 
    return x; 
} 

alert(addOne(y)); // alerts '15' 
alert(addOne(x));  // alerts '16' 

Si tratta di un esempio semplice, e non realistico, ma dimostra il problema bene.

2

Un ottimo articolo è stato recentemente pubblicato da Elijah Manor sul suo blog, Enterprise jQuery. È scritto su Javascript "gotchas" per sviluppatori C#. È una serie di parti e ci sono una serie di aspetti positivi che "convinceranno" le persone a familiarizzare con altre lingue.

Controlla qui: How Good C# Habits can Encourage Bad JavaScript Habits.

+1

Grazie per la menzione. Sono contento che ti sia piaciuto l'articolo. Il post n. 2 è uscito oggi e un terzo post dovrebbe uscire la prossima settimana. –

+1

@Elijah - Nessun problema, e grazie per una grande serie di articoli. Come sviluppatore C# che ha recentemente fatto la mia giusta parte di JavaScript, è stato utile (in particolare le cose false-y). – JasCav

5

Il return dichiarazione deve avere un valore immediatamente successivo, o almeno a partire sulla stessa linea:

return 4; // returns 4 
return {}; // returns an empty object 
return { // returns an empty object 
};   
return  // returns undefined 
{ 
}; 
3

Ajax ottiene/messaggi ad un URI statica possono ottenere cache da IE. Quindi è necessario aggiungere un parametro in continua evoluzione, un modo semplice e veloce è aggiungere new Date().getTime()

+2

Oppure è possibile definire: $ .ajaxSetup ({cache: false}); che aggiungerà la data/ora alla fine di qualsiasi posta/posta di Ajax. – Sphvn