Ir directamente al contenido de esta página

codexexempla.org

Lanzar varias funciones de JavaScript al cargar un documento

Tabla de contenidos

  1. El problema
  2. La solución

El problema

Cuando se enfrentan a un JavaScript, lo navegadores comienzan a interpretar las líneas de código en el momento mismo en el que las descargan. Esto supone que podemos obtener errores inesperados. El ejemplo clásico es addEventListener. Supongamos, por ejemplo, que tenemos esta línea de código:


    document.getElementById('enviar').addEventListener('click',validar,false);
            

Lo que hace es añadir una escucha a un botón identificado como enviar, para lanzar la función validar en el momento en que el usuario haga clic en el mismo, y así prescindir del atributo onclick. La línea es correcta, el botón existe y está correctamente identificado, pero ocurre que la función no se ejecuta. ¿Por qué? Pues lo más común es que el script haya sido vinculado en la cabecera del documento. Así, el navegador lee la líneas de JavaScript y la ejecuta inmediatamente, antes de que haya cargado la parte del documento en la que existe el botón.

La forma más sencilla de evitar este problema es colocar la llamada al archivo .js justo antes del cierre del elemento body, para asegurarse de que todos los posibles elementos sobre los que vaya a trabajar el script se han cargado previamente. Sin embargo, desde el punto de vista del código semántico, el body debe incluir los contenidos del documento, no un script, que pertenece a la capa de comportamientos. Su ubicación correcta es, por tanto, el head.

Lo que se hace es incluir los enunciados en una función y especificar que ésta se ejecute cuando el documento haya terminado de cargar. Eso se puede lograr por medio de una línea como ésta:


    window.onload = nombre_de_la_funcion;
            

Sencillo, ¿verdad?

¿Pero qué ocurre si necesito lanzar más de una función? El primer impulso es hacer algo como esto:


    window.onload = funcion_primera;
    window.onload = funcion_segunda;
    window.onload = funcion_tercera;
            

Sí, todos hemos sido alguna vez así de inocentes, hasta que chocamos con la realidad representada por este ejemplo.

El script del ejemplo es éste:


    function funcion_primera(){ alert("Se ha lanzado la PRIMERA función");}
    function funcion_segunda(){ alert("Se ha lanzado la SEGUNDA función");}
    function funcion_tercera(){ alert("Se ha lanzado la TERCERA función");}
    
    window.onload = funcion_primera;
    window.onload = funcion_segunda;
    window.onload = funcion_tercera;
            

Como vemos, sólo se lanza la última función.

¿A qué se debe? Pues porque aunque al mirar las últimas líneas nos parece que al navegador le decimos algo como «cuando los contenidos de la ventana se carguen me lanzas esta función, y ésta, y ésta», este método de programación intuitiva choca con lo que técnicamente estamos diciendo. Lo que en rigor decimos con window.onload = funcion_primera; es «al método onload del objeto window le asigno el valor de funcion_primera». Podría parecer que es una mera diferencia de jerga, pero no es así, porque al escribir window.onload = funcion_segunda;, volvemos a decir lo mismo para la segunda función, por lo que reasignamos un valor para el mismo método del mismo objeto, con lo que el valor anterior se pierde. Es como si declaráramos una variable varias veces: sólo se mantendría el último valor especificado.

La solución

El problema reside entonces en que window.onload sólo se puede asignar de manera efectiva una vez. Se podría, por tanto asignar a una única función que lanzase todas las demás, en el orden deseado:


    function funcion_primera(){ alert("Se ha lanzado la PRIMERA función");}
    
    function funcion_segunda(){ alert("Se ha lanzado la SEGUNDA función");}
    function funcion_tercera(){ alert("Se ha lanzado la TERCERA función");}
    
    function lanzadera(){
        funcion_primera();
        funcion_segunda();
        funcion_tercera();
    }
    
    window.onload = lanzadera;
            

Como se ve en este segundo ejemplo, funciona.

No obstante, no es la solución ideal a menos que todas y cada una de las funciones que queramos lanzar estén en el mismo archivo .js. Con diversos scripts vinculados nos encontraríamos de nuevo con la situación inicial. Por ello, es más eficaz asignar el evento load a window con la función que se desea ejecutar. Como se puede asignar una escucha de forma independiente para cada función, desde diversos .js se pueden lanzar diversas funciones. En este último ejemplo vinculo tres .js independientes, uno con cada función, y en cada uno añado unas líneas como éstas:


    if (document.addEventListener){
        window.addEventListener('load',la_funcion_que_sea,false);
    } else {
        window.attachEvent('onload',la_funcion_que_sea);
    }
            

El resultado es el mismo que en el segundo ejemplo, pero la solución es más flexible.

Contacto

En virtud de la Ley Orgánica 15/1999 de Protección de Datos de Carácter Personal le informo de que los datos que proporcione no serán empleados para otro fin que el de responder a su mensaje. En especial, me comprometo a no cederlos a terceros ni a emplearlos para enviar información no solicitada.

Del blog de Digital Icon