2016-05-13 2 views
2

In einer Web-App, die es Benutzern ermöglicht, mit Javascript zu spielen, benötige ich eine function main() in ihrem "Programm". Es gibt eine Schaltfläche "Ausführen" und eine Schaltfläche "Bearbeiten". Wenn Sie "run" drücken, wird ein Text aus einem <textarea> verwendet, um einen Skriptblock zu erstellen und in das DOM einzufügen. Dann wird main() aufgerufen.Speichert der Browser kompilierte Versionen von Skriptelementen persistent?

Ich fange window.onerror, um Fehler für den Benutzer anzuzeigen. Dies funktioniert in der Regel in Ordnung. Wenn main() nicht vorhanden ist, wird eine entsprechende Fehlermeldung angezeigt.

Wenn Sie "Bearbeiten" drücken, wird der Skriptblock auf leer gesetzt (script.text = '';) und aus dem DOM entfernt.

Testing, bemerkte ich, dass wenn ich „Programm“ hatte, bestehend aus nur:

function main() { printLn('main here'); } 

es wie erwartet funktioniert, aber wenn ich das geändert zu:

function moon() { printLn('moon here'); } 

anstatt eine Nachricht zu bekommen sagt main() not defined, es funktionierte immer noch wie zuvor, trotz der Tatsache, dass der Skriptblock den "Mond" -Text hatte. Dies passierte weiterhin, wenn ich jedem erstellten Skriptblock eine unverwechselbare ID gab, und wenn ich den Skriptblocktyp vor dem Entfernen auf text/plain änderte.

Das Problem tritt in aktuellen Firefox, Chrome und Opera auf. Sie können sehen, was passiert here

Antwort

4

Die Funktionen sind immer noch definiert, auch wenn Sie das Skript entfernen, das sie definiert hat.

Dies steht in starkem Kontrast zu CSS, bei dem das Entfernen oder Ändern eines Stylesheets die Stile auf der Seite entsprechend entfernt oder aktualisiert.

Es gibt einen guten Grund dafür, und das ist, dass CSS so konzipiert ist, dass es leicht neu bewertet werden kann, wenn Änderungen vorgenommen werden. JavaScript hingegen ist viel zu komplex, als dass der Browser verstehen könnte, was "Entfernen eines Skripts" tatsächlich macht.

Also, vorausgesetzt, Sie haben eine Funktion mit main() ausgeführt, wird es weiterhin existieren, auch wenn Sie es dann löschen.

Mein Vorschlag wäre, eine Schließung zu erstellen, um Ihr Skript auszuführen. Sie können dies tun, mit so etwas wie ...

var input = "........"; // user's input 
var runner = "if(typeof main === 'undefined') {"+ 
    "showErrorMessage('No main() defined');"+ // or whatever your error function is 
    "} else { main(); }"; 
var func = new Function("(function() {"+input+runner+"})()"); 
func(); 

Es ist immer erwähnenswert, dass die globale Reichweite noch zugegriffen werden kann, wie zum Beispiel, wenn der Benutzer vergisst, ihre lokalen Variablen zu var, oder wenn sie geradezu Zugang window.something. Solange es nur auf dem Computer des Benutzers ausgeführt wird, ist dies kein großes Problem, aber wenn Menschen ihre Codes mit anderen teilen können, dann müssen Sie viel vorsichtiger sein.

+0

Das dynamische Definieren und Aufrufen einer Funktion zum Aufruf von main hilft nicht. Main ist eine Funktion in dem Code, den der Benutzer eingegeben hat. Die dynamisch erzeugte Funktion ruft sie auf, und danach gibt typeof main 'function' zurück. Ich frage mich, ob der beste Ansatz darin besteht, den Hauptfunktionsnamen durch Markieren einer inkrementierenden Ganzzahl zu individualisieren, dann die Seite neu zu laden, wenn sie 100 oder eine beliebige Zahl erreicht, um den Müll zu beseitigen. –

+0

@SteveTeale Der Code in dieser Antwort erstellt einen Abschluss, der "main" definiert und aufgerufen wird. Er existiert nicht außerhalb des Abschlusses, sodass keine Eindeutigkeit sichergestellt oder erhöht werden muss. –

+0

Der Benutzer hat einen Skriptblock erstellt, in dem die Funktion main() definiert wurde.Damit die Seite funktioniert, muss diese Funktion aufgerufen werden. –

Verwandte Themen