2010-04-02 11 views
8

Zum Beispiel:Wie überschreiben Eval Funktion in Javascript?

(function() { 
     var proxied = window.eval; 
     window.eval = function() { 
     return proxied.apply(this, arguments); 
     }; 
    })(); 

Aber dieser Code nicht funktioniert.

+17

Es macht mir Angst ein wenig, warum diese tun könnte zu fragen ... – Paddy

+0

Seltsamer ... Denn „Alarm“ und andere Funktionen überschreibt. – ko1ik

+2

Was ist Ihr Anwendungsfall? –

Antwort

8

Sie können nicht. (Es gibt eine begrenzt Art und Weise, es zu tun, aber es ist ziemlich begrenzt und hält nicht die Magie, die bobince talks about.)

eval ist keine wirkliche Funktion JavaScript in mindestens eine Haupt Implementierung (IE JScript (zumindest nicht über IE7; habe die neue IE8-Version nicht getestet), also wirst du sofort in Schwierigkeiten geraten, weil du nicht in der Lage sein wirst, das Original über apply anzurufen (nicht dass das wirklich zählt) für eval).

Die jüngste ECMAScript 5-Spezifikation nicht zulässt, speziell überwiegende eval im Strict-Modus (nicht, dass Sie die strikten Modus dort verwenden), die ich, dass es vermuten läßt sind sehr gute Gründe für das Überschreiben nicht.

+2

Strict Mode verbietet das Aliasing/Overriding 'eval', weil der Interpreter niemals im Voraus sagen könnte, dass ein Funktionsblock keine versteckten Verwendungen von' eval' enthält. Wenn eine Terp (insbesondere JIT) sicher sein kann, dass eine Funktion nur einfachen Code und keine Evals enthält, gibt es eine viel größere Bandbreite an Optimierungen, die sie für den erzeugten Code durchführen kann. – bobince

+0

@bobince: Danke, gut zu wissen. –

+0

Eval Verwendung für dynamische Gebäude ExtJs Komponenten. . Beispiel: ( Ext.data.Connection) Anfrage ({ ... , Erfolg: function (Antwort, entscheidet sich) { \t eval (response.responseText); \t} }) Komponenten gespeichert auf der Server. Diese Verwendung in mehreren Projekten. In dem einen Projekt wird der Rückgabewert von "eval" als eingehender Parameter für eine globale Methode verwendet, andere nicht. Ich brauche diesen Code, um die Funktionalität zu erhalten. – ko1ik

0

Nicht nur sollten Sie dies nicht tun, aber ich denke auch, dass Sie wahrscheinlich nicht können. Erstens ist eval eine globale Funktion und als solche kein Mitglied des Fensters (wie Sie oben versucht haben). Zweitens ist es als globale Funktion sehr wahrscheinlich, dass es in die VM fest verdrahtet ist und nicht überschrieben werden kann.

+2

Eigentlich nennen sowohl die 3. Ausgabe Spezifikation (1999) als auch die 5. Ausgabe Spezifikation (2010) es als eine Eigenschaft des globalen Objekts (das ist "Fenster" in Browsern), in Abschnitt 15.1.2.1. Aber es ist wahr, dass es nicht so zuverlässig umgesetzt wird. –

+0

TJ hat Recht, alle globalen Variablen sind Eigenschaften des Fensterobjekts. Auch fest mit der VM verbunden? Es gibt keine VM, Javascript wird nicht in VM-Byte-Code kompiliert. Schließlich können Sie die meisten globalen Funktionen oder Eigenschaften überschreiben, eval ist nur etwas Besonderes. –

+0

"Es gibt keine VM" - das ist ziemlich falsch. Viele Browser benutzen JS VMs schauen auf TraceMonkey (Firefox) oder V8 (Chrome), was sind das? Sie sind keine Interpeter, da sie JS-Code zu Maschinencode kompilieren. Aber sie sind keine technischen Compiler, da sie nicht die gesamte Maschine aussetzen. Sie stellen dem Code eine Teilmenge (virtuelle Maschine) zur Verfügung. wenn das keine VM ist ... was in aller Welt ist das? "Eval ist nur etwas Besonderes" - ah, also war ich richtig. –

10

eval ist magisch.

function foo() { 
    var a= 1; 
    eval('a+= 1'); 
    alert(a); // 2 
} 

dass eval mit einer Proxy-Funktion ersetzen und Sie haben ein Problem: Im Gegensatz zu einer ‚echten‘ Funktion können sie lokale Variablen in dem Anrufer lesen und schreiben die a+= 1 führen im Rahmen der proxied Funktion anstelle von foo. Abhängig davon, was im bewerteten Code passiert, was dazu führen kann, dass Werte verloren gehen, was zu lokalen, zufälligen Globalen des Proxys und so weiter führt.

Es ist daher unmöglich, eval durch einen voll funktionsfähigen Proxy zu ersetzen. (Für einfache Fälle, die die Einheimischen nicht brauchen, können Sie damit durchkommen.)

+0

Re "unmöglich", es ist möglich, Eval durch einen voll funktionsfähigen Proxy 'MyEval' zu ersetzen, aber Sie brauchen eval ---' MyEval (_ => eval (_)) ' – Pacerier

2

Ich habe dies in FireFox 3.6.2 versucht und es scheint zu funktionieren.

tippte ich diese direkt in der Firebug-Befehlszeile ein:

var proxied = eval; 
eval = function() { alert("ha"); return proxied.apply(this, arguments);}; 
eval(7); 
+2

Das funktioniert nicht zuverlässig über den Browser Und selbst bei Firefox wird Ihre Proxy-Version die Magie vermissen, über die bobince spricht. –

+0

Charge ist nicht definiert [Pause bei diesem Fehler] eval (7); FF 3.6.3pre – ko1ik

+0

Ich weiß, dass es * nicht * funktionieren soll. Ich sage nur, es scheint zu funktionieren. –

4

Obwohl es nicht tragbar, arbeitet der folgende Ansatz in einigen Orten, an denen es sonst nicht (wie es ES5 die Anforderungen, die ein erfüllt) es abgerufen werden ‚Standard-Funktion‘ als Referenz in einem Member, keinen Wert und B) in den Ergebnissen - ES5 #15.1.2)

(function() { 
    var proxied = window.eval 
    with({get eval(){ console.log('eval called'); return proxied }}) { 
    /* client code */ 
    } 
})() 

Dies gilt natürlich nur, wenn Sie den Client-Code in eine mit() Anweisung wickeln kann; obwohl das in vielen Situationen nicht schwer sein sollte. Offensichtlich kann derselbe Ansatz window mit einem anderen Objekt mit all seinen Eigenschaften und einem Getter-Proxy eval überschatten.

Umgebungen, die die get-Anweisung von SpiderMonkey nicht unterstützen, können möglicherweise die defineProperty von ES5 verwenden. Schau dir das selbst an.

+0

Errata: Wenn Sie ein '}' in 'proxied}' – johnjohn

+2

@johnjohn in Stack Overflow vermissen, können Sie die Antworten anderer Personen bearbeiten, um Änderungen vorzuschlagen. Nur für zukünftige Referenz. Aber danke! Fest. (= – ELLIOTTCABLE

+0

Ehrfürchtige Idee. Aber scheint eine schreckliche Praxis. – Oriol

0

Vielleicht habe ich die Frage nicht richtig verstehen, aber ich „außer Kraft setzen“ eval() durch eine myEval() Funktion zu schaffen, die die ursprüngliche eval() Inneren hat und zusätzlich Schritte in myEval() auszuführen.

function myEval = function(value){ 
    //do your stuff here 
    //for example 
    try { 
     value = eval(value) 
    } catch (error) { 
     console.log(error) 
     value = NaN 
    } 
    return value 
} 
+0

Sie sollten eine Erklärung für den Code bereitstellen, den Sie gepostet haben. –

Verwandte Themen