¿Por qué document.body es nulo en mi javascript?


132

Aquí está mi breve documento HTML.

¿Por qué la consola Chrome está notando este error?

"Tipo de error no detectado: ¿No se puede llamar al método 'appendChild' de null"?

<html>
<head>
    <title>Javascript Tests</title>

    <script type="text/javascript">

        var mySpan = document.createElement("span");
        mySpan.innerHTML = "This is my span!";

        mySpan.style.color = "red";
        document.body.appendChild(mySpan);

        alert("Why does the span change after this alert? Not before?");

    </script>
</head>
<body>

</body>
</html>

Estoy usando Google Chrome.
John Hoffman

Respuestas:


180

El cuerpo aún no se ha definido en este punto. En general, desea crear todos los elementos antes de ejecutar javascript que usa estos elementos. En este caso tienes algunos javascript en la headsección que usa body. No es genial

Desea envolver este código en un window.onloadcontrolador o colocarlo después de la <body>etiqueta (como se menciona en e-bacho 2.0 ).

<head>
    <title>Javascript Tests</title>

    <script type="text/javascript">
      window.onload = function() {
        var mySpan = document.createElement("span");
        mySpan.innerHTML = "This is my span!";

        mySpan.style.color = "red";
        document.body.appendChild(mySpan);

        alert("Why does the span change after this alert? Not before?");
      }

    </script>
</head>

Ver demo .


1
Gracias a que te refieres ¿No tengo una etiqueta corporal?
John Hoffman

55
La página se lee de arriba a abajo y JavaScript se ejecuta en el camino. Tienes algunos javascript en la headsección que se está ejecutando. Pero bodyparte del html, tal vez, aún no se ha descargado. O se descarga, pero todavía no se evalúa en este momento. Por lo tanto, no existe en el DOM.
Sergio Tulentsev

3
¿Qué sucede si no desea anular una carga existente definida en otro archivo?
Tom Brito

1
@TomBrito: "o colóquelo después de la <body>etiqueta"
Sergio Tulentsev

1
Un poco tarde, pero también podría usar addEventListener para adjuntar el oyente a la ventana, sin reemplazar los existentes.
edvilme

36

Su script se está ejecutando bodyincluso antes de que el elemento se haya cargado.

Hay un par de formas de solucionar esto.

  • Envuelva su código en una devolución de llamada de carga DOM:

    Envuelva su lógica en un oyente de eventos DOMContentLoaded.

    Al hacerlo, la devolución de llamada se ejecutará cuando el bodyelemento se haya cargado.

    document.addEventListener('DOMContentLoaded', function () {
        // ...
        // Place code here.
        // ...
    });

    Dependiendo de sus necesidades, también puede adjuntar un loaddetector de eventos al windowobjeto:

    window.addEventListener('load', function () {
        // ...
        // Place code here.
        // ...
    });

    Para la diferencia entre los eventos DOMContentLoadedy load, vea esta pregunta .

  • Mueva la posición de su <script>elemento y cargue JavaScript al final:

    En este momento, su <script>elemento se está cargando en el <head>elemento de su documento. Esto significa que se ejecutará antes de que se bodyhaya cargado. Los desarrolladores de Google recomiendan mover las <script>etiquetas al final de su página para que todo el contenido HTML se procese antes de que se procese JavaScript.

    <!DOCTYPE html>
    <html>
    <head></head>
    <body>
      <p>Some paragraph</p>
      <!-- End of HTML content in the body tag -->
    
      <script>
        <!-- Place your script tags here. -->
      </script>
    </body>
    </html>

2
Creo que esto es más completo y actual que la respuesta aceptada.
theUtherSide

8

Agregue su código al evento de carga. La respuesta aceptada muestra esto correctamente, sin embargo, esa respuesta, así como todas las demás al momento de escribir, también sugieren colocar la etiqueta del script después de la etiqueta del cuerpo de cierre,.

Esto no es html válido. Sin embargo, hará que su código funcione, porque los navegadores son demasiado amables;)

Consulte esta respuesta para obtener más información. ¿Es incorrecto colocar la etiqueta <script> después de la etiqueta </body>?

Votó otras respuestas por este motivo.


4

O agrega esta parte

<script type="text/javascript">

    var mySpan = document.createElement("span");
    mySpan.innerHTML = "This is my span!";

    mySpan.style.color = "red";
    document.body.appendChild(mySpan);

    alert("Why does the span change after this alert? Not before?");

</script>

después del HTML, como:

    <html>
    <head>...</head>
    <body>...</body>
   <script type="text/javascript">
        var mySpan = document.createElement("span");
        mySpan.innerHTML = "This is my span!";

        mySpan.style.color = "red";
        document.body.appendChild(mySpan);

        alert("Why does the span change after this alert? Not before?");

    </script>

    </html>

1

El navegador analiza su html de arriba hacia abajo, su script se ejecuta antes de cargar el cuerpo. Para arreglar poner script después del cuerpo.

  <html>
  <head>
       <title> Javascript Tests </title> 
  </head>
 <body>
 </body>
  <script type="text/javascript">

    var mySpan = document.createElement("span");
    mySpan.innerHTML = "This is my span!";

    mySpan.style.color = "red";
    document.body.appendChild(mySpan);

    alert("Why does the span change after this alert? Not before?");

</script>
</html>

0

document.body aún no está disponible cuando se ejecuta su código.

Lo que puedes hacer en su lugar:

var docBody=document.getElementsByTagName("body")[0];
docBody.appendChild(mySpan);

@Jake, ¿podrías ser más específico? ¿Algún ejemplo de navegador / versión donde no funciona?
Christophe

Chrome @ 39 y Firefox @ 33
Jake

@Jake ok, entonces mi respuesta fue correcta al momento de escribir ;-) Gracias por alertarme, haré algunas pruebas y publicaré una actualización.
Christophe
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.