Anteriormente, exploramos el principio de funcionamiento de JavaScript desde el mecanismo de análisis del motor JavaScript. Ahora usamos un ejemplo más vívido para ilustrar el orden de ejecución del código JavaScript en la página. Si el mecanismo de trabajo del motor JavaScript es relativamente profundo porque pertenece al comportamiento subyacente, entonces el orden de ejecución del código JavaScript es más vívido, porque podemos sentir intuitivamente este orden de ejecución. Por supuesto, el orden de ejecución del código JavaScript. Es relativamente complejo, por lo que también es necesario perfilar el lenguaje JavaScript antes de sumergirse en él.
1.1 Ejecutar código JavaScript en orden de flujo de documentos HTML
En primer lugar, los lectores deben saber que el proceso de análisis de documentos HTML en el navegador es el siguiente: el navegador analiza gradualmente la estructura de la página y la información de arriba a abajo de acuerdo con el flujo del documento. El código JavaScript como script incrustado también debe contarse como un componente del documento HTML, por lo que el orden de ejecución del código JavaScript durante la carga también se determina en función del orden en que aparece la etiqueta del script <script>. Por ejemplo, explore la página de documentación a continuación y verá que el código se analiza paso a paso de arriba a abajo.
Copie el código de código de la siguiente manera:
<guión>
alert("Guión superior");
</script>
<html><cabeza>
<guión>
alerta("script principal");
</script>
<título></título>
</cabeza>
<cuerpo>
<guión>
alerta("script de página");
</script>
</cuerpo></html>
<guión>
alerta("script inferior");
</script>
Si se importa un script de archivo JavaScript externo a través del atributo src de la etiqueta de script <script>, también se ejecutará en el orden en que aparecen sus declaraciones y el proceso de ejecución es parte de la carga del documento. La ejecución no se retrasará porque es un archivo JavaScript externo. Por ejemplo, mueva los scripts en las áreas de encabezado y cuerpo del documento anterior a archivos JavaScript externos y luego impórtelos a través del atributo src. Si continúa obteniendo una vista previa del documento de la página, verá el mismo orden de ejecución.
Copie el código de código de la siguiente manera:
<guión>
alert("Guión superior");
</script>
<html>
<cabeza>
<script src="//www.VeVB.COm/head.js"></script>
<título></título>
</cabeza>
<cuerpo>
<script src="//www.VeVB.COm/body.js"></script>
</cuerpo>
</html>
<guión>
alerta("script inferior");
</script>
1.2 La relación entre precompilación y orden de ejecución
En Javascript, la función es el primer tipo de Javascript. Cuando escribimos una función, en realidad solo estamos creando una entidad de tipo función.
Así como podemos escribirlo de esta forma:
Copie el código de código de la siguiente manera:
funciónHola()
{
alerta("Hola");
}
Hola();
varHola = función()
{
alerta("Hola");
}
Hola();
De hecho, son todos iguales. Pero cuando modificamos las funciones nos encontraremos con problemas muy extraños.
Copie el código de código de la siguiente manera:
<scripttype="texto/javascript">
funciónHola() {
alerta("Hola");
}
Hola();
funciónHola() {
alerta("Hola mundo");
}
Hola();
</script>
Veremos el resultado así: Hello World aparece dos veces seguidas.
En lugar del Hola y Hola Mundo que imaginamos.
Esto se debe a que Javascript no se interpreta y ejecuta completamente en orden. En cambio, Javascript se "precompila" antes de la interpretación. Durante el proceso de precompilación, las funciones definidas se ejecutarán primero y se crearán todas las variables var. El valor predeterminado no está definido para mejorar. eficiencia en la ejecución del programa.
En otras palabras, el código anterior en realidad está precompilado por el motor JS en esta forma:
Copie el código de código de la siguiente manera:
<scripttype="texto/javascript">
varHola = función() {
alerta("Hola");
}
Hola = función() {
alerta("Hola mundo");
}
Hola();
Hola();
</script>
Podemos ver claramente en el código anterior que las funciones también son datos y variables. También podemos asignar (reasignar) valores a "funciones".
Por supuesto, para prevenir esta situación también podemos hacer esto:
Copie el código de código de la siguiente manera:
<scripttype="texto/javascript">
funciónHola() {
alerta("Hola");
}
Hola();
</script>
<scripttype="texto/javascript">
funciónHola() {
alerta("Hola mundo");
}
Hola();
</script>
De esta forma, el programa se divide en dos secciones y el motor JS no las juntará.
Cuando el motor JavaScript analiza un script, procesa todas las variables y funciones declaradas durante la precompilación.
Haga lo siguiente:
1. Antes de la ejecución, se realizará una operación similar a la "precompilación": primero, se creará un objeto activo en el entorno de ejecución actual y las variables declaradas con var se establecerán como atributos del objeto activo, pero en este momento , la asignación de estas variables será indefinida, y aquellas funciones definidas con función también se agregan como propiedades del objeto activo, y sus valores son exactamente la definición de la función.
2. Durante la fase de interpretación y ejecución, cuando es necesario analizar una variable, primero se buscará en el objeto activo del entorno de ejecución actual. Si no se encuentra y el propietario del entorno de ejecución tiene el atributo de prototipo, se buscará. se buscará desde la cadena del prototipo; de lo contrario, se buscará según la cadena de alcance. Al encontrar una declaración como var a = ..., se asignará un valor a la variable correspondiente (nota: la asignación de la variable se completa durante la fase de interpretación y ejecución. Si la variable se usa antes de esto, su valor será indefinido). Por lo tanto, parecerá que no se informará ningún error cuando el intérprete de JavaScript ejecute el siguiente script:
Copie el código de código de la siguiente manera:
alerta(a); // valor de retorno indefinido
var a =1;
alerta(a); // valor de retorno 1
Dado que las declaraciones de variables se procesan en el momento de la precompilación, son visibles para todo el código durante la ejecución. Sin embargo, también verá que al ejecutar el código anterior, el valor solicitado no está definido, no 1. Esto se debe a que el proceso de inicialización de variables ocurre durante la ejecución, no durante la precompilación. Durante la ejecución, el intérprete de JavaScript analiza el código en orden. Si a una variable no se le asigna un valor en la línea de código anterior, el intérprete de JavaScript utilizará el valor predeterminado de indefinido. Dado que a la variable a se le asigna un valor en la segunda línea, la tercera línea de código le indicará que el valor de la variable a es 1, no indefinido.
De manera similar, en el siguiente ejemplo, es legal llamar a la función antes de declararla y se puede analizar correctamente, por lo que el valor de retorno es 1.
Copie el código de código de la siguiente manera:
f(); // Llamar a la función, valor de retorno 1
función f(){
alerta(1);
}
Sin embargo, si la función se define de la siguiente manera, el intérprete de JavaScript generará un error de sintaxis.
Copie el código de código de la siguiente manera:
f(); // Llama a la función y devuelve el error de sintaxis
varf = función(){
alerta(1);
}
Esto se debe a que la función definida en el ejemplo anterior solo se asigna a la variable f como valor. Por lo tanto, durante el período de precompilación, el intérprete de JavaScript solo puede procesar la declaración de la variable f, y el valor de la variable f solo puede procesar. Se debe presionar durante el período de ejecución. Si las asignaciones se realizan secuencialmente, naturalmente ocurrirá un error de sintaxis, lo que indicará que no se puede encontrar el objeto f.
Adiós algunos ejemplos:
Copie el código de código de la siguiente manera:
<tipo de script="texto/javascript">
/*Durante el proceso de precompilación, func es un atributo en el objeto activo en el entorno de ventana y el valor es una función que cubre el valor indefinido*/
alerta(func); //función func(){alerta("¡hola!")}
var func = "esta es una variable"
función función(){
alerta ("¡hola!")
}
/*Durante la ejecución, se encontró var y se reasignó a "esta es una variable"*/
alerta(func); //esta es una variable
</script>
Copie el código de código de la siguiente manera:
<tipo de script="texto/javascript">
var nombre = "feng" función función()
{
/* Primero, asigne el nombre a indefinido en el entorno func y luego busque el atributo de nombre del objeto activo en el entorno func durante la ejecución. En este momento, el valor se ha precompilado en indefinido, por lo que la salida es indefinida, no. feng*/
alerta(nombre); //nombre var indefinido = "JSF";
alerta(nombre); //JSF
}
función();
alerta(nombre);
//feng
</script>
Aunque las declaraciones de variables y funciones pueden estar en cualquier parte del documento, es una buena práctica declarar variables y funciones globales antes de todo el código JavaScript, e inicializar y asignar variables. Dentro de una función, las variables se declaran primero y luego se hace referencia a ellas.
1.3 Ejecutar código JavaScript en bloques
Los llamados bloques de código son segmentos de código separados por etiquetas <script>. Por ejemplo, las dos etiquetas <script> siguientes representan dos bloques de código JavaScript.
Copie el código de código de la siguiente manera:
<guión>
// bloque de código JavaScript 1
var a =1;
</script>
<guión>
// bloque de código JavaScript 2
función f(){
alerta(1);
}
</script>
Cuando el intérprete de JavaScript ejecuta un script, lo ejecuta en bloques. En términos sencillos, si el navegador encuentra una etiqueta <script> al analizar el flujo de documentos HTML, el intérprete de JavaScript esperará hasta que se cargue el bloque de código, primero precompilará el bloque de código y luego lo ejecutará. Después de la ejecución, el navegador continúa analizando el flujo de documentos HTML a continuación y el intérprete de JavaScript está listo para procesar el siguiente bloque de código.
Dado que JavaScript se ejecuta en bloques, si llama a una variable o función declarada en un bloque posterior en un bloque de JavaScript, se generará un error de sintaxis. Por ejemplo, cuando el intérprete de JavaScript ejecuta el siguiente código, generará un error de sintaxis que mostrará que la variable a no está definida y no se puede encontrar el objeto f.
Copie el código de código de la siguiente manera:
<guión>
// bloque de código JavaScript 1
alerta(a);
F();
</script>
<guión>
// bloque de código JavaScript 2
var a =1;
función f(){
alerta(1);
}
</script>
Aunque JavaScript se ejecuta en bloques, diferentes bloques pertenecen al mismo ámbito global, lo que significa que se pueden compartir variables y funciones entre bloques.
1.4 Utilice el mecanismo de eventos para cambiar el orden de ejecución de JavaScript
Debido a que JavaScript procesa el código en fragmentos y sigue el orden de análisis del flujo de documentos HTML, verá errores de sintaxis en el ejemplo anterior. Pero cuando se carga el flujo de documentos, dicho error no ocurrirá si se accede nuevamente. Por ejemplo, si el código que accede a las variables y funciones en el segundo bloque de código se coloca en la función del evento de inicialización de la página, no habrá errores de sintaxis.
Copie el código de código de la siguiente manera:
<guión>
// bloque de código JavaScript 1
window.onload = function(){ // Función de manejo de eventos de inicialización de página
alerta(a);
F();
}
</script>
<guión>
// bloque de código JavaScript 2
var a =1;
función f(){
alerta(1);
}
</script>
Por razones de seguridad, generalmente solo permitimos la ejecución de código JavaScript después de que se inicializa la página. Esto puede evitar el impacto de la velocidad de la red en la ejecución de JavaScript y también evitar las restricciones en la ejecución de JavaScript causadas por el flujo de documentos HTML.
Aviso
Si hay varios controladores de eventos windows.onload en una página, solo el último es válido. Para resolver este problema, puede colocar todos los scripts o funciones de llamada en el mismo controlador de eventos onload, por ejemplo:
Copie el código de código de la siguiente manera:
ventana.onload = función(){
f1();
f2();
f3();
}
Y de esta manera, el orden de ejecución de las funciones se puede cambiar simplemente ajustando el orden de llamada de las funciones en el controlador de eventos de carga.
Además de los eventos de inicialización de la página, también podemos cambiar el orden de ejecución del código JavaScript a través de varios eventos interactivos, como eventos del mouse, eventos del teclado, activadores del reloj, etc. Para obtener una explicación detallada, consulte el Capítulo 14.
1.5 Orden de ejecución de los scripts de salida de JavaScript
En el desarrollo de JavaScript, el método write() del objeto de documento se utiliza a menudo para generar scripts de JavaScript. Entonces, ¿cómo se ejecutan estos scripts de salida dinámica? Por ejemplo:
Copie el código de código de la siguiente manera:
document.write('<script type="text/javascript">');
documento.write('f();');
document.write('función f(){');
document.write('alerta(1);');
documento.write('}');
document.write('</script>');
Al ejecutar el código anterior, encontraremos que: el método document.write() primero escribe la cadena del script de salida en la ubicación del documento donde se encuentra el script. Después de analizar el contenido del documento donde se encuentra document.write(), El navegador continúa analizando el contenido de salida de document.write () y luego analiza los documentos HTML posteriores en orden. En otras palabras, la cadena de código generada por el script JavaScript se ejecutará inmediatamente después de la salida.
Tenga en cuenta que la cadena de script JavaScript generada mediante el método document.write() debe colocarse en la etiqueta <script> que se genera al mismo tiempo. De lo contrario, el intérprete de JavaScript no podrá reconocer estos códigos JavaScript legales y lo hará. se mostrará como una cadena normal en el documento de la página. Por ejemplo, el siguiente código mostrará el código JavaScript en lugar de ejecutarlo.
Copie el código de código de la siguiente manera:
documento.write('f();');
document.write('función f(){');
document.write('alerta(1);');
documento.write(');');
Sin embargo, existen ciertos riesgos al generar y ejecutar scripts a través del método document.write(), porque diferentes motores de JavaScript los ejecutan en diferentes órdenes y pueden ocurrir errores en diferentes navegadores durante el análisis.
Ø Problema 1: No se pueden encontrar las variables o funciones declaradas en el archivo JavaScript externo importado a través del método document.write(). Por ejemplo, mire el código de muestra a continuación.
Copie el código de código de la siguiente manera:
document.write('<script type="text/javascript" src="//www.VeVB.COm/test.js">
</script>');
document.write('<script type="text/javascript">');
document.write('alert(n);'); // IE indica que no se puede encontrar la variable n
document.write('</script>');
alert(n+1); // Todos los navegadores indicarán que no se puede encontrar la variable n.
El código del archivo JavaScript externo (test.js) es el siguiente:
Copie el código de código de la siguiente manera:
varn = 1;
Cuando se prueba en diferentes navegadores, encontrará un error de sintaxis y no se puede encontrar la variable n. En otras palabras, si accede en un bloque de código JavaScript a las variables contenidas en el archivo JavaScript externo importado en la salida del script mediante el método document.write() en este bloque de código, se mostrará un error de sintaxis. Al mismo tiempo, si está en el navegador IE, no solo en el script, sino también en el script de salida, le indicará que no se puede encontrar la variable de salida importada al archivo JavaScript externo (la expresión es un poco larga y complicada, los lectores que no comprendan pueden intentar ejecutar el código anterior (se puede entender).
Ø Pregunta 2: Los diferentes motores de JavaScript tienen órdenes de ejecución ligeramente diferentes para los scripts de importación externos de salida. Por ejemplo, mire el código de muestra a continuación.
Copie el código de código de la siguiente manera:
<tipo de script="texto/javascript">
document.write('<script type="text/javascript" src="http://shaozhuqing.com/test1.js">
</script>');
document.write('<script type="text/javascript">');
documento.write('alerta(2);')
document.write('alerta(n+2);');
document.write('</script>');
</script>
<tipo de script="texto/javascript">
alerta(n+3);
</script>
El código para el archivo JavaScript externo (test1.js) se muestra a continuación.
Copie el código de código de la siguiente manera:
varn = 1;
alerta(n);
La secuencia de ejecución en el navegador IE se muestra en la Figura 1-6.
Figura 1-6 La secuencia de ejecución y los errores de sintaxis provocados por el navegador IE 7
El orden de ejecución en los navegadores que cumplen con los estándares DOM es diferente al de los navegadores IE y no hay errores de sintaxis. La Figura 1-7 muestra el orden de ejecución en el navegador Firefox 3.0.
Figura 1-7 Secuencia de ejecución del navegador Firefox 3 y errores de sintaxis indicados
Solucionar las diferentes órdenes de ejecución de los distintos navegadores y posibles fallos. Podemos colocar todos los archivos externos importados usando el script de salida en bloques de código independientes, de modo que este problema pueda evitarse de acuerdo con el orden de ejecución de los bloques de código JavaScript presentados anteriormente. Por ejemplo, para el ejemplo anterior, puedes diseñarlo así:
Copie el código de código de la siguiente manera:
<tipo de script="texto/javascript">
document.write('<script type="text/javascript" src="//www.VeVB.COm/test1.js"></script>');
</script>
<tipo de script="texto/javascript">
document.write('<script type="text/javascript">');
document.write('alert(2);') // Consejo 2
document.write('alert(n+2);'); // Consejo 3
document.write('</script>');
alerta(n+3); // Consejo 4
</script>
<tipo de script="texto/javascript">
alerta(n+4); // Consejo 5
</script>
De esta manera, el código anterior se puede ejecutar en orden en diferentes navegadores y el orden de salida es 1, 2, 3, 4 y 5. El motivo del problema es: una contradicción entre el script importado de salida y el bloque de código JavaScript actual. Si se genera por separado, no habrá conflicto.