Frage

Die Funktion eval ist eine leistungsfähige und einfache Möglichkeit, Code dynamisch zu generieren, so was sind die Einschränkungen?

War es hilfreich?

Lösung

  1. Bei unsachgemäßem Gebrauch von eval öffnet sich Ihr Code für Injection-Angriffe

  2. Debuggen kann schwieriger sein (Keine Zeilennummern, usw.)

  3. eval'd Code ausgeführt wird langsamer (keine Gelegenheit / cache eval'd Code zu kompilieren)

Edit: Wie @ Jeff Walden in den Kommentaren weist darauf hin, # 3 ist weniger wahr, als sie es jedoch im Jahr 2008 war, während einige Caching von kompilierten Skripte nur auf Skripte beschränkt dies geschehen wird, kann die wiederholt werden eval'd mit keine Modifikation. Eine wahrscheinlichere Szenario ist, dass Sie Skripte werden eval'ing, die jedes Mal leichte Modifikation unterzogen wurden und als solche nicht im Cache gespeichert werden können. Sagen wir einfach, dass einige eval'd Code langsamer ausgeführt wird.

Andere Tipps

eval ist nicht immer böse. Es gibt Zeiten, in denen es perfekt geeignet ist.

Allerdings eval ist derzeit und historisch massiv über, die von Menschen, die nicht wissen, was sie tun. Dazu gehören Menschen JavaScript Tutorials schreiben, leider, und in einigen Fällen kann dies in der Tat Sicherheit Folgen haben - oder, häufiger, einfache Fehler. So desto mehr können wir ein Fragezeichen über eval werfen tun, desto besser. Jedes Mal, wenn eval Sie brauchen geistige Gesundheit zu überprüfen, was Sie tun, weil die Chancen sind könnte man es besser, sicherer, sauberer Weise tun.

ein allzu typisches Beispiel zu geben, setzen die Farbe eines Elements mit einer ID in der Variablen ‚Kartoffel‘ gespeichert:

eval('document.' + potato + '.style.color = "red"');

Wenn die Autoren der Art von Code über einen Anhaltspunkt über die Grundlagen der haben, wie JavaScript-Objekte arbeiten, habe sie erkennt, dass eckige Klammern anstelle von wörtlichen Punktnamen verwendet werden, wodurch die Notwendigkeit für eval vermieden:

document[potato].style.color = 'red';

... die viel einfacher ist als auch weniger potenziell Buggy zu lesen.

(Aber dann jemand, der / eigentlich / wussten, was sie sagen würde taten:

document.getElementById(potato).style.color = 'red';

, die zuverlässiger ist als der zwielichtige alte Trick von Elementen direkt aus dem Dokument-Objekt DOM zugreifen.)

Ich glaube, es ist, weil es jede JavaScript-Funktion aus einem String ausführen kann. Mit ihm macht es einfacher für Menschen Rogue-Code in die Anwendung zu injizieren.

Zwei Punkte in den Sinn kommen:

  1. Sicherheit (aber solange Sie die Zeichenfolge erzeugen selbst ausgewertet werden, könnte dies kein Thema sein)

  2. Performance: bis der Code ausgeführt wird, unbekannt ist, ist es nicht optimiert werden kann. (Über JavaScript und Leistung, sicher Steve Yegge Präsentation )

Übergeben von Benutzereingaben an eval () ist ein Sicherheitsrisiko, sondern auch jeder Aufruf von eval () eine neue Instanz des JavaScript-Interpreter erstellt. Dies kann eine Ressource Schwein sein.

Es ist in der Regel nur dann ein Problem, wenn Sie eval Benutzereingabe vorbei sind.

In erster Linie ist es viel schwieriger zu pflegen und zu debuggen. Es ist wie ein goto. Sie können es verwenden, aber es macht es schwieriger, auf den Menschen Probleme und schwerer zu finden, die späten Änderungen vornehmen können müssen.

Eine Sache im Auge zu behalten ist, dass Sie oft eval () verwenden Code in einer ansonsten eingeschränkten Umgebung auszuführen - Social-Networking-Sites, die bestimmten JavaScript-Funktionen blockieren kann sie manchmal täuscht durch Brechen in einem eval-Block nach oben -

eval('al' + 'er' + 't(\'' + 'hi there!' + '\')');

Also, wenn Sie schauen, um etwas JavaScript-Code auszuführen, wo es sonst nicht erlaubt werden könnte ( Myspace , ich suche dich ...), dann kann eval () ein nützlicher Trick sein.

Doch für alle oben genannten Gründen sollten Sie es nicht für Ihren eigenen Code verwenden, wo Sie die vollständige Kontrolle haben - es ist einfach nicht notwendig, und besser weg, um der Stange ‚tricky JavaScript Hacks‘ degradiert

Wenn Sie eval lassen () ein dynamischer Inhalt (durch cgi oder Eingang), ist es als sicher und solide wie alle anderen JavaScript in Ihrer Seite ein.

Zusammen mit dem Rest der Antworten, ich glaube nicht, eval Aussagen erweitern Minimierung haben.

Es ist ein mögliches Sicherheitsrisiko, es einen anderen Umfang der Ausführung hat, und ist sehr ineffizient, da es eine völlig neue Skripting-Umgebung für die Ausführung des Codes erzeugt. Sehen Sie hier einige weitere Informationen:. eval

Es ist sehr nützlich, aber, und verwendet mit Maßen viele gute Funktionalität hinzufügen können.

Es sei denn, Sie sind zu 100% sicher, dass der Code ausgewertet wird von einer vertrauenswürdigen Quelle ist (in der Regel Ihrer eigene Anwendung), dann ist es eine todsichere Methode, Ihr System auf einen Cross-Site-Scripting-Angriff ausgesetzt wird.

Ich weiß, diese Diskussion ist alt, aber ich mag diese Ansatz von Google und wollte dieses Gefühl mit anderen teilen;)

Die andere Sache ist, dass je besser Sie erhalten je mehr Sie versuchen, Sie zu verstehen und schließlich nur noch nicht glauben, dass etwas gut oder schlecht ist, nur weil jemand gesagt :) Dies ist ein sehr inspirierend Video , die mir geholfen, mehr zu denken, von mir :) GUTE PRAXIS ist gut, aber sie nicht mindelessly verwenden:)

Es ist nicht unbedingt so schlecht, vorausgesetzt, Sie wissen, was Kontext Sie verwenden es in.

Wenn Ihre Anwendung mit eval() ein Objekt von einem JSON zu schaffen, die wieder von einem XMLHttpRequest zu Ihrer eigenen Website, die von vertrauenswürdigem serverseitigen Code erstellt, ist es wahrscheinlich kein Problem.

Untrusted clientseitige JavaScript-Code kann so viel sowieso nicht. die Sache zur Verfügung gestellt Sie eval() sind die Ausführung auf einer vernünftigen Quelle gekommen ist, du bist in Ordnung.

Es stark reduziert Ihr Niveau des Vertrauens um die Sicherheit.

Wenn Sie den Benutzer zur Eingabe einiger logischen Funktionen wollen und bewerten für und die oder dann ist die JavaScript-Funktion eval perfekt. Ich kann zwei Strings und eval(uate) string1 === string2 akzeptieren, etc.

Wenn Sie die Verwendung von eval beschmutzen () in Ihrem Code, denken Sie daran, das Mantra „eval () ist böse.“

Diese Funktion nimmt eine beliebige Zeichenfolge und führt sie als JavaScript-Code. Wenn der Code in Frage wird im Voraus (nicht bestimmt zur Laufzeit) bekannt ist, gibt es keinen Grund zu verwenden, eval (). Wenn der Code zur Laufzeit dynamisch erzeugt wird, gibt es oft einen besseren Weg erreicht das Ziel ohne eval (). Zum Beispiel mit nur eckiger Klammer-Notation Zugang dynamische Eigenschaften sind besser und einfacher:

// antipattern
var property = "name";
alert(eval("obj." + property));

// preferred
var property = "name";
alert(obj[property]);

Mit eval() hat auch Auswirkungen auf die Sicherheit, da Sie die Ausführung von Code sein könnte (für Beispiel aus dem Netz kommen), die manipuliert wurde. Dies ist eine gemeinsame Antipattern, wenn sie mit einer JSON Antwort von einem Ajax-Request handelt. In den Fällen, es ist besser, die Browser integrierte Methoden zu verwenden, um die JSON-Antwort zu analysieren zu machen sicher, es ist sicher und gültig. Für Browser, die JSON.parse() nicht nativ unterstützt, können Sie verwenden, um eine Bibliothek von JSON.org.

Es ist auch wichtig, dass vorbei Saiten zu erinnern setInterval(), setTimeout(), und der Function() Konstruktor ist, zum größten Teil, ähnlich wie eval() verwenden und daher sollte vermieden werden.

Hinter den Kulissen ist Javascript noch bewerten und ausführen die Zeichenfolge, die Sie als Programmcode übergeben:

// antipatterns
setTimeout("myFunc()", 1000);
setTimeout("myFunc(1, 2, 3)", 1000);

// preferred
setTimeout(myFunc, 1000);
setTimeout(function () {
myFunc(1, 2, 3);
}, 1000);

Um die neue Funktion () Konstruktor ist ähnlich wie eval () und soll angegangen werden mit Vorsicht. Es könnte ein leistungsfähiges Konstrukt sein, wird aber oft missbraucht. Wenn Sie unbedingt verwenden eval(), können Sie mit neuer Funktion () statt betrachten.

Es gibt ein kleines Potential profitieren, da der Code in neuer Funktion ausgewertet () wird in einer lokalen Funktion ausgeführt werden Umfang, so dass alle mit var definierten Variablen im Code ausgewertet wird nicht werden Globals automatisch.

Eine andere Möglichkeit, die automatische Globals zu verhindern, ist das wickeln eval() Anruf in eine unmittelbare Funktion.

Neben den möglichen Sicherheitsproblemen, wenn Sie vom Benutzer übermittelten Code ausführen, die meiste Zeit ist es eine bessere Art und Weise, die nicht wieder Parsen mit sich bringt, den Code jedes Mal ausgeführt wird. Anonyme Funktionen oder Objekteigenschaften können die meisten Anwendungen von eval und ersetzen viel sicherer und schneller.

Dies kann eher ein Problem als die nächste Generation wird von Browsern mit einigem Geschmack eines JavaScript-Compiler kommen. Code über Eval ausgeführt wird, kann nicht so gut wie der Rest Ihres JavaScript gegen diese neueren Browser auszuführen. Jemand sollte eine gewisse Profilierung tun.

Dies ist ein guter Artikel sprechen über eval und wie es ist, nicht ein Übel: http://www.nczonline.net/ Blog / 2013/06/25 / eval-isnt-Übel-just-mißverstanden /

  

Ich sage nicht, sollten Sie gehen laufen und beginnen mit eval ()   überall. In der Tat gibt es nur sehr wenige gute Anwendungsfälle für das Laufen   eval () überhaupt. Es gibt auf jeden Fall Bedenken mit Code Klarheit,   debugability, und sicherlich die Leistung, die nicht übersehen werden sollte.   Aber Sie sollten keine Angst, es zu benutzen, wenn Sie einen Fall, wo   eval () macht Sinn. Versuchen Sie es mit ihm nicht zuerst, aber lassen Sie sich nicht jemand erschrecken   Sie Ihren Code in das Denken ist zerbrechlicher oder weniger sicher, wenn eval ()   in geeigneter Weise verwendet wird.

eval () ist sehr leistungsfähig und kann verwendet werden, um eine JS-Anweisung auszuführen oder einen Ausdruck auswerten. Aber die Frage ist nicht über die Verwendung von eval (), sondern lässt nur einige sagen, wie die Zeichenfolge, die Sie mit eval ausgeführt wird () durch eine böswillige Partei betroffen ist. Am Ende werden Sie bösartigen Code ausführen. Mit Macht kommt große Verantwortung. verwenden Sie es so klug ist, Sie es verwenden.  Das ist nicht viel zu Funktion eval () verwandt, aber dieser Artikel hat ziemlich gute Informationen:   http://blogs.popart.com/2009/07/javascript-injection- Angriffe / Wenn Sie die Grundlagen der eval suchen () hier: https://developer.mozilla.org/en-US / docs / Web / JavaScript / Reference / Global_Objects / eval

Ich werde nicht versuchen, etwas zu widerlegen, die bisher, aber ich werde diese Verwendung von eval bieten (), die (soweit ich weiß) kann nicht auf andere Weise erfolgen. Wahrscheinlich gibt es andere Möglichkeiten, dies zu codieren, und wahrscheinlich Möglichkeiten, es zu optimieren, aber dies ist Langschrift getan und ohne Schnickschnack aus Gründen der Übersichtlichkeit halber eine Verwendung von eval zu veranschaulichen, die wirklich keine andere Alternativen haben. Das heißt: dynamische (oder genauer) Objektnamen programmically erstellt (wie auf Werte gegen)

.
//Place this in a common/global JS lib:
var NS = function(namespace){
    var namespaceParts = String(namespace).split(".");
    var namespaceToTest = "";
    for(var i = 0; i < namespaceParts.length; i++){
        if(i === 0){
            namespaceToTest = namespaceParts[i];
        }
        else{
            namespaceToTest = namespaceToTest + "." + namespaceParts[i];
        }

        if(eval('typeof ' + namespaceToTest) === "undefined"){
            eval(namespaceToTest + ' = {}');
        }
    }
    return eval(namespace);
}


//Then, use this in your class definition libs:
NS('Root.Namespace').Class = function(settings){
  //Class constructor code here
}
//some generic method:
Root.Namespace.Class.prototype.Method = function(args){
    //Code goes here
    //this.MyOtherMethod("foo"));  // => "foo"
    return true;
}


//Then, in your applications, use this to instantiate an instance of your class:
var anInstanceOfClass = new Root.Namespace.Class(settings);

EDIT: durch die Art und Weise, würde ich nicht vorschlagen (für alle aus Sicherheitsgründen zuvor darauf hingewiesen), die Sie stützen Sie Namen auf Benutzereingaben Objekt. Ich kann keinen guten Grund vorstellen, Sie wollen würden, dass, obwohl zu tun. Trotzdem dachte ich, es würde darauf hinweisen, dass es nicht eine gute Idee wäre:)

Der JavaScript-Engine verfügt über eine Reihe von Performance-Optimierungen, die es während der Kompilierung-Phase durchführt. Einige dieser einkochen zu der Möglichkeit, den Code im Wesentlichen statisch zu analysieren, wie es Lexes und vorge bestimmen, wo alle variablen und Funktionsdeklarationen sind, so dass es weniger Aufwand nimmt Identifikatoren während der Ausführung zu lösen.

Aber wenn der Motor einen eval findet (..) in dem Code, hat es im Wesentlichen zu der Annahme, dass alle das Bewusstsein für Identifiziererorteingabemittel ungültig sein kann, weil es nicht bei lexing Zeit wissen können, genau das, was Code, den Sie eval passieren kann ( ..), um den lexikalischen Gültigkeitsbereich, oder der Inhalt des Objekts ändern können Sie weitergeben, die mit einem neuen lexikalischen Bereich erstellen konsultiert werden.

Mit anderen Worten, in der pessimistischen Sinn, die meisten dieser Optimierungen wäre es sinnlos zu machen sind, wenn eval (..) vorhanden ist, so ist es nicht einfach die Optimierungen überhaupt durchführen.

Das erklärt alles.

Referenz:

https: //github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/ch2.md#eval

https: //github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/ch2.md#performance

Es ist nicht immer eine schlechte Idee. Nehmen Sie zum Beispiel, Code-Generierung. Ich schrieb vor kurzem eine Bibliothek namens Hyperbar , die die Lücke zwischen virtual-dom und Lenker . Es tut dies durch einen Lenker Template-Parsing und Umwandlung in hyperscript , die anschließend durch virtuellen dom verwendet wird. Die hyperscript wird als Zeichenkette erzeugte erste und bevor es zurückkehrt, eval() es es in ausführbaren Code zu drehen. Ich habe eval() in dieser besonderen Situation genau das Gegenteil des Bösen gefunden.

Im Grunde genommen von

<div>
    {{#each names}}
        <span>{{this}}</span>
    {{/each}}
</div>

Um dies zu

(function (state) {
    var Runtime = Hyperbars.Runtime;
    var context = state;
    return h('div', {}, [Runtime.each(context['names'], context, function (context, parent, options) {
        return [h('span', {}, [options['@index'], context])]
    })])
}.bind({}))

Die Leistung von eval() ist kein Problem in einer Situation wie diese, weil Sie nur die generierte Zeichenfolge einmal interpretieren müssen und dann die ausführbare Ausgabe über viele Male wiederverwendet werden.

Sie können sehen, wie der Code-Generierung erreicht wurde, wenn Sie neugierig sind hier .

Ich würde sogar so weit gehen zu sagen, dass es nicht wirklich wichtig, wenn Sie eval() in Javascript verwenden, die in Browsern ausgeführt wird. * (Vorbehalt)

Alle modernen Browser haben eine Entwicklerkonsole, wo man sowieso beliebige Javascript ausführen kann und jeder halbintelligenten Entwickler an Ihrer JS Quelle aussehen kann und setzen, was Bits es sie brauchen die Entwickler-Konsole in zu tun, was sie wollen.

* Solange der Server-Endpunkte die korrekte Validierung und Hygienisierung von Benutzer gelieferten Werte haben, sollte es keine Rolle, was in der Client-Seite Javascript wird analysiert und eval'd.

Wenn Sie fragen, ob es geeignet ist jedoch eval() in PHP zu verwenden, ist die Antwort NO , wenn Sie auf Weiße Liste alle Werte, die auf Ihre eval-Anweisung übergeben werden können, .

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top