è male usare eval per convertire una stringa in una funzione?

Ho sentito molte opinioni diverse su eval () e sono un po ‘insicuri se va bene usare eval () in questo contesto:

Diciamo che ho un object come questo:

var bla = { blubb: function (callback) { //GET some stuff via ajax //call the callback } } 

E una stringa come questa:

  var someString = "bla.blubb"; 

È malvagio valutare la stringa per chiamare la funzione (e il callback)?

 var callMe = eval(someString) callMe(function(){ alert('yay')! }); 

ho sentito molte opinioni diverse su eval ()

eval non è male in generale, ci sono applicazioni per questo.

non so se va bene usare eval () in questo contesto

No, non è OK per questo. Esiste una soluzione molto migliore utilizzando l’ operatore membro di notazione di parentesi semplice. Poiché questo viene chiesto ogni giorno su SO, posso elencare centinaia di duplicati qui (solo i primi risultati di Google):

  • Convertire la stringa nella notazione dei punti per ottenere il riferimento all’object
  • Converti object notazione punto javascript in object nidificato
  • Accesso agli oggetti JavaScript nidificati con chiave di stringa
  • accedere all’object tramite il percorso di stringa della syntax del punto
  • Converti la stringa JavaScript nella notazione a punti in un riferimento a un object
  • Accedere alle proprietà secondarie dell’object utilizzando una stringa di notazione dei punti

Supponiamo che il tuo intero progetto non sia totalmente malvagio (ma un po ‘).

Ciò significherebbe che limiti e specifica ciò che hai in someString . Ad esempio potrebbe essere il percorso di un object e la sua funzione che chiamereste senza alcun argomento (che lo rende molto meno pericoloso) e con il contesto l’object globale.

Quindi è facile analizzare la stringa e chiamare la funzione senza eval . Questo sarebbe più sicuro. Per esempio :

 window.a = {b:{c:function(){console.log('here')}}}; var someString = "abc"; var path = someString.split('.'); var f = window; for (var i=0; i 

Un miglioramento sarebbe quello di correggere un object radice (e non una finestra) per evitare qualsiasi tipo di chiamata.

Non dimenticare che puoi usare una “valutazione sicura” in javascript se sai come saranno i tuoi oggetti.

all’interno di un ambito:

 this.foo = { bar:function(){return "baz"}}; // some code. var obj = "foo"; var param = "bar"; this[obj][param](); // same as this.foo.bar(); 

A meno che tu non abbia a che fare con alcune cose specifiche (come ad esempio il template), non dovresti usare eval per chiamare gli oggetti.

È di nuovo malvagio perché è difficile per il debug. Un approccio migliore è usare qualcosa come:

 function getValue(namespace, parent) { var parts = namespace.split('.'), current = parent || window; for (var i = 0; i < parts.length; i += 1) { if (current[parts[i]]) { current = current[parts[i]]; } else { if (i >= parts.length - 1) return undefined; } } return current; } var foo = { bar: { baz: function () { alert('baz'); } } }; var f = getValue('foo.bar.baz'); //true if (typeof f === 'function') { f(); } 

Il codice è più di un singolo eval('foo.bar.baz') ma puoi capire cosa sta realmente accadendo e persino eseguirne il debug con i punti di interruzione.

Se parliamo di prestazioni qui ci sono alcuni esempi di jsperf:

  1. http://jsperf.com/eval-vs-loop
  2. http://jsperf.com/eval-vs-loop/2