¿Se interpreta JavaScript por diseño?

70

Soy cauteloso de hacer esta pregunta porque podría parecer demasiado fastidioso. Acabo de abrir JavaScript: The Definitive Guide, y dice que está en la primera página del capítulo 1

  

"JavaScript es una programación interpretada de alto nivel, dinámica y sin tipo   idioma "

¿Debo entender que la parte interpretada es un requisito en la especificación del lenguaje, o es engañoso decir que el lenguaje es un lenguaje de programación interpretado cuando se respeta la diferencia entre un lenguaje y sus múltiples implementaciones?

Aparentemente no hay compiladores estáticos para JavaScript - enlace así que quizás sea solo un reflejo de esto.

    
pregunta Matt Esch 06.03.2012 - 16:49

4 respuestas

47
  

¿Debo entender que la parte interpretada es un requisito en la especificación del lenguaje, o es engañoso decir que el lenguaje es un lenguaje de programación interpretado cuando se respeta la diferencia entre un lenguaje y sus múltiples implementaciones?

Los geeks del lenguaje EcmaScript a menudo usan el término "intérprete de ES" para referirse a una implementación de EcmaScript, pero la spec No usa ese término. La descripción general del idioma en particular describe el idioma en términos de intérprete:

  

ECMAScript se basa en objetos: el lenguaje básico y las instalaciones de host son proporcionados por objetos, y un programa ECMAScript es un grupo de objetos en comunicación.

EcmaScript asume un "entorno de host" que se define como un proveedor de definiciones de objetos, incluidos todos aquellos que permiten I / O o cualquier otro enlace al mundo exterior, pero no requiere un intérprete.

La semántica de las declaraciones y expresiones en el lenguaje se definen en términos de especificación de finalización que se implementan de forma trivial en un intérprete, pero la especificación no requiere eso.

  

8.9 El tipo de especificación de finalización

     

El tipo de finalización se usa para explicar el comportamiento de las declaraciones ( break , continue , return y throw ) que realizan transferencias de control no locales. Los valores del tipo de Compleción son triples del formulario ( tipo , valor , destino ), donde tipo es uno de normal , interrupción , continuar , devolver o lanzar , valor es cualquier valor de lenguaje ECMAScript o vacío , y destino es cualquier identificador de ECMAScript o vacío .

     

El término "finalización abrupta" se refiere a cualquier finalización con un tipo que no sea normal .

Las transferencias de control no locales se pueden convertir en arreglos de instrucciones con saltos que permiten la compilación de código nativo o de byte.

"Motor EcmaScript" puede ser una mejor manera de expresar la misma idea.

  

Aparentemente no hay compiladores estáticos para JavaScript

Esto no es cierto. El "intérprete" de V8 compila internamente el código nativo, Rhino opcionalmente compila internamente el código de bytes de Java y varios intérpretes de Mozilla ({Trace, Spider, Jager} Monkey) usan un compilador JIT.

V8 :

  

V8 aumenta el rendimiento al compilar JavaScript en el código de máquina nativo antes de ejecutarlo, en lugar de ejecutar el bytecode o interpretarlo.

Rhino :

public final void setOptimizationLevel(int optimizationLevel)
     

Establezca el nivel de optimización actual.   Se espera que el nivel de optimización sea un número entero entre -1 y 9. Cualquier valor negativo se interpretará como -1, y cualquier valor mayor que 9 se interpretará como 9. Un nivel de optimización de -1 indica que el modo interpretativo siempre será usado. Los niveles del 0 al 9 indican que se pueden generar archivos de clase. Los niveles de optimización más altos compensan el rendimiento en tiempo de compilación para el rendimiento en tiempo de ejecución. El nivel del optimizador no se puede establecer en más de -1 si el paquete del optimizador no existe en el tiempo de ejecución.

TraceMonkey :

  

TraceMonkey agrega compilación de código nativo al motor JavaScript® de Mozilla (conocido como “SpiderMonkey”). Se basa en una técnica desarrollada en UC Irvine llamada "árboles de traza", y se basa en el código y las ideas compartidas con el proyecto Tamarin Tracing. El resultado neto es un aumento masivo de la velocidad tanto en el contenido de Chrome como en el de la página web.

    
respondido por el Mike Samuel 06.03.2012 - 18:16
19

La máquina virtual JavaScript V8 utilizada en Chrome no incluye un intérprete. En su lugar, consta de dos compiladores y compila el código sobre la marcha. Uno de los compiladores se ejecuta rápidamente pero genera un código ineficiente, el otro es un compilador de optimización.

Puedo entender por qué algunas personas consideran este "engaño", ya que V8 toma el código fuente como entrada cada vez que se ejecuta el código y el usuario debe tener instalado V8. Pero considere un compilador que emite un ejecutable que incluye un intérprete completo y un bytecode. Entonces tendrías un programa independiente. Simplemente no sería muy eficiente.

    
respondido por el Jørgen Fogh 06.03.2012 - 17:08
18

La aparición de compiladores JIT para lenguajes de script ha difuminado la línea entre la compilación y la interpretación hasta un punto en el que la pregunta no significa mucho. ¿Es solo una interpretación cuando el motor lee una línea de código y lo ejecuta inmediatamente? (Los scripts de shell todavía se implementan normalmente de esta manera). ¿Es la interpretación cuando el motor toma todo el archivo, lo compila de inmediato en algún código de byte y luego interpreta el código de byte? (El motor Mozilla de la primera etapa funciona de esta manera, al igual que CPython). ¿Se interpreta cuando el motor analiza una función a la vez y JIT la compila en un código nativo? ¿Qué pasa con los motores que compilan todo el archivo en código de byte, luego JIT una función a la vez, según sea necesario? (La mayoría de los motores de scripts en estos días funcionan de esta manera, y la máquina virtual principal de Java funciona de esta manera también, excepto que la compilación a un código de bytes ocurre antes de tiempo).

Hay muchos matices entre la compilación y la interpretación.

Creo que la definición más útil para la interpretación es "se alimenta el código fuente del programa en el momento de la ejecución, sin un paso de avance por separado". Por esta definición, todos los motores de JavaScript son intérpretes. Pero ciertamente esta no es la única definición posible de interpretación.

¿Pero está diseñado JavaScript para la interpretación? En cierto modo, sí: tiene una función eval , así como el constructor Function , que puede proporcionar el código del programa como una cadena que se ejecutará. La capacidad de construir dinámicamente el código del programa en el tiempo de ejecución requiere que el motor sea capaz de interpretar el código fuente. Pero esto no significa que no puedas hacer todo lo demás antes de tiempo. Incluso en un lenguaje compilado como C ++ y C #, puede tomar el código fuente, compilarlo en la memoria al nuevo código de máquina y luego ejecutarlo. Incluso hay bibliotecas para eso: LLVM + Clang en C ++ y el proyecto Roslyn en C #.

Además, el mecanismo de entrega para JavaScript es el código fuente; no hay un código de byte reconocido. C # y Java tienen su código de byte oficial, y todos esperan que C ++ se entregue como código de máquina. Pero esto todavía no es un aspecto inherente al lenguaje, solo un escenario de uso dominante. De hecho, el código ActionScript relativo de Flash en Flash se entrega como código de bytes (el compilador de Flash precompila todos los scripts).

    
respondido por el Sebastian Redl 07.05.2015 - 10:33
4

No hay una definición totalmente acordada de 'interpretado' versus 'compilado'. En la distinción clásica, los idiomas compilados producen un ejecutable binario independiente, mientras que los idiomas interpretados requieren un tiempo de ejecución implementado para ejecutar el código. Las máquinas virtuales, el código de bytes, etc. desdibujan la distinción.

Pero aquí hay una posible definición útil: un lenguaje interpretado es un idioma en el que el tiempo de ejecución del idioma estándar puede tomar el texto del código fuente como entrada y ejecutarlo. Según esa definición, los scripts de Perl, Python, Ruby, JavaScript y shell y similares se interpretan (incluso si utilizan pasos intermedios como bytecode o incluso código nativo). Java, C #, C etc. no lo son. Y JavaScript se interpreta por definición, incluso si la especificación no usa la palabra exacta.

    
respondido por el JacquesB 07.05.2015 - 14:19

Lea otras preguntas en las etiquetas