2012-02-01 7 views
27

Molti programmatori dicono che è una cattiva praticadi utilizzare la funzione di eval():Perché esiste eval()?

When is JavaScript's eval() not evil?

mi piacerebbe prendere un momento per affrontare la premessa della sua domanda - che eval() è "male" ...

Is this eval() dangerous?

Buggy EVALED codice può violare le proprietà di sicurezza altrettanto facilmente come codice sorgente buggy ...

Why not eval() JSON?

Ci sono un certo numero di modi che la sicurezza può essere compromessa ...

Is there ever a good reason to use eval()?

Sì - quando non c'è altro modo per realizzare il compito dato con un ragionevole livello di chiarezza ... Questo elimina il 99% dei casi in cui si usa eval ...

Why is eval unsafe in javascript?

Il pericolo di eval alza solo la sua brutta testa quando si sta servendo un copione scritto da Alice a Bob utente per il browser di bob a eval ...


Quindi perché esiste in primo luogo?

+3

Perché gli uomini scalano le montagne? –

+2

@JoelCoehoorn, per arrivare dall'altra parte? –

risposta

7

Perché a volte lo è un bisogno. Gli stessi motivi per/contro l'utilizzo di eval in JavaScript possono probabilmente essere condivisi con l'uso della reflection in Java, ad esempio.

Tuttavia, sono d'accordo con tutto ciò che hai citato nella tua domanda. Molte ragioni per utilizzarlo sono sconsiderate e meglio fatte in modo diverso - ma a volte c'è ancora bisogno o è semplicemente la "scelta migliore" rispetto ad altre alternative disponibili. (Mi concentrerei sulle risposte a Is there ever a good reason to use eval()? per ulteriori motivi.)

+1 per la vostra domanda per una buona ricerca.

+2

Aggiungendo felicemente un altro +1 per la buona ricerca. Il 99% dei casi evitabili è vero. L'1% - cose come http://dean.edwards.name/packer/ - sarebbe stato pazzesco scrivere senza di esso, però;) –

+0

@Chris Grande di un caso d'uso valido. Stavo cercando di scoprire se [Firebug Lite] (http://getfirebug.com/firebuglite) utilizza 'eval' per il suo controllo JS ma si è perso nel loro codice. – millimoose

+0

C'è una recente pubblicazione di ricerca sull'argomento a cui potresti essere interessato. Le loro conclusioni corrispondono alla tua intuizione/esperienza. Vedi la mia risposta. – ewernli

2

La funzione eval() è come le forbici. Sei un adulto, è tua responsabilità non correre con loro.

Ho visto la filosofia di progettazione di linguaggi dinamici (come JavaScript) riassunti come preferenziali per consentire alle persone intelligenti di fare cose intelligenti sopra cercando di impedire alle persone stupide di fare cose stupide. (Purtroppo non riesco a ricordare la fonte o il fraseggio originale.)

Se si è preoccupati di introdurre bug con eval, è possibile utilizzare strict mode.Sembra prevenire alcuni dei problemi relativi alla progettazione della funzionalità. (Cioè, come funzione "magia" permesso di clobber spazio dei nomi.)

8

eval() esiste perché a volte si desidera dare completa controllo programmatico della vostra applicazione per codificare passata in fase di esecuzione.

Lingue senza una caratteristica eval() può sicuramente fornire (?? Un sottoinsieme tutti) di questa funzionalità chiedendo ogni programmatore di scrivere essenzialmente la loro proprioeval() - lex l'ingresso, analizzare l'input, creare nuovi oggetti, se necessario, eseguire metodi o funzioni su di essi tramite semplici confronti tra stringhe o simili. In pratica, duplica l'intero interprete già esistente ed è debugato e veloce.

6

C'è una pubblicazione exacty ricerca su questo argomento:

The Eval That Men Do -- A Large-scale Study of the Use of Eval in JavaScript Applications
Mirror on Wayback Machine

è per me la risposta più esauriente a questa domanda fino ad oggi.

Citazione di astratto:

Noi abbiamo registrato il comportamento di 337 MB di stringhe dati come argomenti a 550,358 chiamate alla funzione eval esercitato in oltre 10.000 siti web.

tra l'altro, hanno identificato 9 categorie di ricorrenti eval:

  1. JSON - Una stringa JSON o variante.
  2. JSONP - Una stringa JSON imbottita.
  3. Libreria -Una o più de fi nizioni di funzione.
  4. Lettura: accesso in lettura a una proprietà dell'oggetto .
  5. Assegna - Assegnazione a una variabile locale o alla proprietà dell'oggetto .
  6. Typeof - Type test expression.
  7. Prova - Trivial try/catch block.
  8. Chiamata: chiamata funzione/metodo semplice.
  9. vuoto - Stringa vuota o vuota.

Un frammento dalla conclusione (che è troppo lungo per essere citato entierly):

[...] Mentre molti usi eval erano legittime, molti erano inutili e potrebbe essere sostituito con equivalente e codice più sicuro. Abbiamo iniziato questo lavoro con la speranza che mostrasse che eval può essere sostituito da altre funzioni . Purtroppo i nostri dati non supportano questa conclusione. [...]

Una carta vale la pena leggere.

6

Eval è in realtà una funzionalità potente e ci sono alcune cose che sono impossibile fare a meno. Ad esempio:

  1. Valuta il codice ricevuto da un server remoto. (Dire che vuoi creare un sito che può essere controllato da remoto inviando un codice JavaScript?)
  2. Valuta il codice scritto dall'utente. Senza eval, non è possibile programmare, ad esempio, un editor online/REPL.
  3. Creazione di funzioni di lunghezza arbitraria dinamicamente (function.length è di sola lettura, quindi l'unico modo è utilizzare eval).
  4. Caricamento di uno script e restituzione del valore. Se il tuo script è, ad esempio, una funzione di auto-chiamata, e vuoi valutarlo e ottenerne il risultato (es .: my_result = get_script_result("foo.js")), l'unico modo di programmare la funzione get_script_result è usando eval al suo interno.
  5. Ricreazione di una funzione in una chiusura diversa.

E tutto ciò che vorresti fare è creare codice al volo.

Il motivo per cui è considerato "malvagio" è perché è un classico usato dai novizi per fare cose che la lingua può gestire in modo nativo. Ad esempio, il codice qui sotto:

age_of_erick = 34; 
age_of_john = 21; 
person = "erick"; 
eval("console.log('age_of_"+person+"')"); 

E il codice qui sotto:

age = {erick:34, john:21}; 
person = "erick"; 
console.log(age["erick"]); 

Entrambi fanno la stessa cosa, tranne uno analizza una stringa, genera codice da essa, compila in codice macchina e poi corre, mentre l'altro legge un valore da un hash, che è molto più veloce.

0

Eval esiste per semplificare le attività in JavaScript. Puoi usarlo per valutare più affermazioni. Invece di dover trovare un altro modo puoi usare eval per fare queste cose. Anche se scoraggiato, ha un notevole potere e uso.