por - tostring javascript
¿En qué motores de Javascript Function.prototype.toString no devuelve el código fuente de esa función? (2)
EDITAR: Para ser explícito, no estoy buscando consejos u opiniones sobre el mérito cualitativo de los diversos problemas que implica la funcionalidad en cuestión; tampoco estoy buscando una solución confiable para un problema práctico; Simplemente estoy buscando respuestas técnicas y verificables a la pregunta en el título. He adjuntado la pregunta con una lista de navegadores no conformes.
El uso del método .toString
una función normalmente generará el código fuente de esa función . El problema es que este comportamiento no se especifica , la especificación se abstiene de comprometerse con el comportamiento cuando se aplica a las funciones. La consola de Chrome incluso le dirá (cuando le pasa algo que no sea una función a Function.toString.call
), Function.prototype.toString no es genérico
Esta publicación del blog sugiere que esto se puede usar como un método para producir una sintaxis legible para cadenas de varias líneas (almacenando la cadena como un comentario de varias líneas en el cuerpo de una función no operativa ). El autor sugiere este uso en el contexto de la escritura de aplicaciones Node.js con la cláusula de que este comportamiento solo es confiable porque Node.js se ejecuta en un entorno controlado. Pero en la web nativa de Javascript, todo puede venir e interpretarlo, y no debemos confiar en un comportamiento no especificado.
En la práctica, sin embargo, he configurado un violín que muestra un cuadro de selección cuyo contenido está determinado por una cadena multilínea grande para probar el código, y cada navegador en mi estación de trabajo (Chrome 27, Firefox 21, Opera 12, Safari 5 , Internet Explorer 8) se ejecuta según lo previsto.
¿Qué motores de Javascript actuales no se comportan de la siguiente manera?
Dado que:
function uncomment(fn){
return fn.toString().split(////*/n|/n/*///g).slice(1,-1).join();
}
El seguimiento:
uncomment(function(){/*
erg
arg
*/});
Debe salir:
erg
arg
Lista de navegadores no conformes:
- Firefox 16
- ...
¿Qué motores de Javascript actuales no se comportan de esta manera?
Su pregunta no está realmente bien definida, dado que no ha definido "popular". ¿Es popular el IE6? IE5? IE4? ¿Netscape Navigator? ¿Lince? La única forma de responder correctamente a su pregunta es enumerar los navegadores que desea admitir y verificarlos. Desafortunadamente, la tabla de kangax http://kangax.github.io/es5-compat-table/# no prueba Function.prototype.toString
La consola de Chrome incluso le dirá (cuando pase algo que no sea una función o Function.toString.call), Function.prototype.toString no es genérico
obligatorio en la especificación
la especificación se abstiene de hacer cualquier compromiso en cuanto a cuál debería ser el comportamiento cuando se aplica a las funciones
El comportamiento requerido se especifica en ECMA-262 versión 1 (desde 1997, http://www.ecma-international.org/publications/files/ECMA-ST-ARCH/ECMA-262,%201st%20edition,%20June%201997.pdf ) Tienes que perseguirlo:
- http://www.ecma-international.org/ecma-262/5.1/#sec-4.3.24 "function ... miembro del tipo de objeto que es una instancia del constructor de funciones incorporado estándar y que puede ser invocado como una subrutina "
A partir de eso, deducimos que las funciones son objetos.
- http://www.ecma-international.org/ecma-262/5.1/#sec-9.8 "Let primValue be ToPrimitive (argumento de entrada, pista String)."
Entonces, ¿qué es ToPrimitive?
- http://www.ecma-international.org/ecma-262/5.1/#sec-9.1 "El valor predeterminado de un objeto se recupera llamando al [[DefaultValue]] método interno del objeto, pasando la sugerencia opcional PreferredType . "
Así que necesitamos saber qué hace DefaultValue
- http://www.ecma-international.org/ecma-262/5.1/#sec-8.12.8 (muchas palabras que básicamente dicen si la cosa tiene un método toString, luego llámala)
Ahora solo necesitamos encontrar dónde se describe Function.prototype.toString:
- http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.4.2 "Se devuelve una representación de la función dependiente de la implementación. Esta representación tiene la sintaxis de una FunctionDeclaration. Tenga en cuenta en particular que uso y ubicación de espacios en blanco, terminadores de línea y punto y coma dentro de la cadena de representación depende de la implementación ".
Por lo tanto, se le garantiza que obtendrá una representación javascript adecuada (no un libro de IL), pero no necesariamente con los comentarios. Por ejemplo, la técnica se rompe en Firefox 16 (pero luego tienes que preguntar si es actual).
Así que Kangax ha vuelto al tema (intrigado por el hecho de que Angular usa este truco para la funcionalidad principal en el código del lado del cliente) y escribió un análisis de la práctica, y produjo una tabla de prueba para el estado de descompilación de funciones. en Javascript .
Los puntos para llevar son que:
- La técnica solo es remotamente confiable para declaraciones de funciones definidas por el usuario.
- Algunos navegadores móviles antiguos aún colapsarán el código funcional, supuestamente por razones de rendimiento.
- Otros navegadores antiguos revelarán código optimizado, algo así como lo que podría obtener de Closure Compiler.
- Sin embargo, otros eliminarán los comentarios y alterarán los espacios en blanco.
- Internet Explorer ocasionalmente agregará comentarios y espacios en blanco alrededor de las funciones.
- El equipo de AngularJS parece pensar que esta técnica es lo suficientemente robusta como para incluirla en su biblioteca sin una advertencia explícita. Luego, tokenizan (!) El código y lo vuelven a evaluar (!!).
Para mis propósitos, esto me hace razonablemente seguro de que puedo hacer algo relativamente poco exigente, como detectar si una función tiene un nombre en mayúscula o no, analizándola de la siguiente manera:
/function/s*[A-Z]/.test( fn )