2010-04-02 28 views
8

Por ejemplo:¿Cómo anular la función eval en javascript?

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

Pero este código no está funcionando.

+17

Me asusta un poco a preguntarse por las que podría estar haciendo esto ... – Paddy

+0

extraño ... Porque "alerta" y otras funciones es reemplazar. – ko1ik

+2

¿Cuál es tu caso de uso? –

Respuesta

8

No puede. (hay una limitada forma de hacerlo, pero es bastante limitado y no mantiene la magia que bobince talks about.)

eval no es una verdadera función de JavaScript en al menos una aplicación importante (JScript de IE , al menos no a través de IE7; no han probado la nueva versión de IE8), así que de inmediato tendrás problemas, porque no podrás llamar al original a través del apply (no es lo que realmente importa) para eval).

La reciente especificación ECMAScript 5 no permite específicamente primordial eval en modo estricto (no es que usted está utilizando el modo estricto no), lo que me hace sospechar que hay muy buenas razones por no primordiales ella.

+2

El modo estricto no permite aliasing/overriding 'eval' porque el intérprete nunca podrá decir de antemano que un bloque de función no contenía ningún uso oculto de' eval'. Si un terp (especialmente el JIT) puede estar seguro de que una función contiene solo código simple y no evals, hay un rango mucho más amplio de optimizaciones que puede realizar en el código generado. – bobince

+0

@bobince: Gracias, es bueno saberlo. –

+0

Eval uso para componentes dinámicos de construcción ExtJs. . Ejemplo: Ext.data.Connection() solicitud ({ ... , el éxito: la función (respuesta, opta) { \t eval (response.responseText); \t}} ) componentes se almacenan en el servidor. Esto usando en varios proyectos. En el valor de retorno del proyecto de "eval" usar como parámetro de entrada para un método global, otro - no usar. Necesito este código para mantener la funcionalidad. – ko1ik

0

No solo no debe hacer esto, sino que también creo que probablemente no pueda hacerlo. En primer lugar, eval es una función global y, como tal, no es miembro de la ventana (como lo ha intentado anteriormente). En segundo lugar, como función global, es muy probable que esté conectada a la máquina virtual y no pueda sobrescribirse.

+2

En realidad, tanto la especificación de la 3ª edición (1999) como la 5ª edición (2010) lo califican como una propiedad del objeto global (que es 'ventana' en los navegadores), en la sección 15.1.2.1. Pero es verdad que no está * implementado de manera confiable * de esa manera. –

+0

TJ tiene razón, todas las variables globales son propiedades del objeto ventana. Además, ¿está conectado a la VM? No hay VM, javascript no se compila en algún código de byte de VM. Por último, puede anular la mayoría de las funciones o propiedades globales, eval es simplemente especial. –

+0

"No hay VM" - eso es bastante incorrecto. Muchos navegadores, las VM de JS, ven TraceMonkey (firefox) o V8 (Chrome), ¿cuáles son? No son intermediarios, ya que compilan código JS para código de máquina. Pero técnicamente no son compiladores, ya que no exponen toda la máquina. Exponen un subconjunto (máquina virtual) al código. si eso no es una máquina virtual ... ¿qué demonios es? "Eval es simplemente especial" - ah, estaba en lo cierto. –

10

eval es mágico. A diferencia de una función 'real', se puede leer y escribir variables locales en la persona que llama:

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

reemplazar ese eval con una función de proxy y tienes un problema: la a+= 1 ejecuta en el ámbito de la función proxied en lugar de foo. Dependiendo de lo que esté sucediendo en el código evadido que podría hacer que los valores se pierdan, daños en los valores globales locales accidentales del proxy, y así sucesivamente.

Por lo tanto, es imposible reemplazar eval con un proxy que funcione correctamente. (Para casos simples que no necesitan los lugareños, puede salirse con la suya.)

+0

Re "imposible", es posible reemplazar eval con un proxy que funcione completamente 'MyEval', pero necesita eval ---' MyEval (_ => eval (_)) ' – Pacerier

2

Intenté esto en FireFox 3.6.2 y parece que funciona.

he escrito esto directamente en la línea de comandos FireBug:

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

Eso no funciona confiablemente entre navegadores , e incluso en Firefox, su versión proxiada no tendrá la magia de la que bobince habla. –

+0

lote no está definido [Romper este error] eval (7); FF 3.6.3pre – ko1ik

+0

Sé que * no * supone * que funcione. Solo digo que parece funcionar. –

4

Aunque no es portátil, el siguiente enfoque funciona en algunos lugares en los que de otro modo sería no (ya que satisface los requerimientos de ES5 que a) ser recuperada 'función interna estándar' como una referencia en un MemberExpression, no es un valor y B) que da lugar a la - ES5 #15.1.2)

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

obviamente, esto sólo se aplica si se puede envolver el código de cliente en una sentencia with(); aunque en muchas situaciones, eso no debería ser difícil. Obviamente, el mismo enfoque puede sombrear window con otro objeto con todas sus propiedades, y un 0xproxy directo.

Los entornos que no son compatibles con la declaración get de SpiderMonkey, pueden utilizar el defineProperty de ES5. Míralo tú mismo.

+0

Errata: falta un '}' en 'proxy '' – johnjohn

+2

@johnjohn en Stack Overflow, puede editar las respuestas de otras personas para sugerir cambios. Solo para referencia futura. ¡Pero gracias! Fijo. (= – ELLIOTTCABLE

+0

Increíble idea. Pero parece una práctica horrenda. – Oriol

0

Tal vez no entendieron la pregunta correctamente, pero "anular" eval() creando una función myEval() que tiene el original eval() su interior y ejecutar etapas de adición de myEval().

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

Deberías proporcionar alguna explicación para el código que publicaste. –

Cuestiones relacionadas