Dlaczego document.body ma wartość null w moim javascript?


136

Oto mój krótki dokument HTML.

Dlaczego konsola Chrome zauważa ten błąd:

„Uncaught TypeError: Cannot call method 'appendChild' of 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>

Używam Google Chrome.
— John Hoffman,

Odpowiedzi:


182

Na tym etapie ciało nie zostało jeszcze zdefiniowane. Ogólnie rzecz biorąc, chcesz utworzyć wszystkie elementy przed wykonaniem javascript, który używa tych elementów. W tym przypadku masz trochę javascript w headsekcji, która używa body. Nie fajnie.

Chcesz zawinąć ten kod w window.onloadprocedurze obsługi lub umieść go po tej <body>zmiennej (jak wspomniano przez 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>

Zobacz demo .


1
Dziękuję, co masz na myśli? Nie mam tagu body?
— John Hoffman,

5
Strona jest czytana od góry do dołu i po drodze wykonywany jest javascript. W wykonywanej headsekcji znajduje się skrypt javascript . Ale bodybyć może część html nie została jeszcze nawet pobrana. Lub jest pobierany, ale na tym etapie nadal nie jest oceniany. Więc nie istnieje w DOM.
— Sergio Tulentsev

3
Co jeśli nie chcesz zastępować istniejącego obciążenia zdefiniowanego w innym pliku?
— Tom Brito

1
@TomBrito: „lub umieścić go po tym <body>tagiem”
— Sergio Tulentsev

1
Trochę za późno, ale przydałby się również addEventListener do dołączenia detektora do okna, bez zastępowania istniejących.
— edvilme

38

Twój skrypt jest wykonywany przed bodyzaładowaniem elementu.

Istnieje kilka sposobów obejścia tego problemu.

  • Umieść swój kod w wywołaniu zwrotnym DOM Load:

    Umieść swoją logikę w nasłuchiwaniu zdarzeń DOMContentLoaded.

    W ten sposób wywołanie zwrotne zostanie wykonane po bodyzaładowaniu elementu.

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

    W zależności od potrzeb możesz alternatywnie dołączyć loaddo windowobiektu detektor zdarzeń :

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

    Aby poznać różnicę między zdarzeniami DOMContentLoadedi load, zobacz to pytanie .

  • Przenieś pozycję <script>elementu i załaduj JavaScript na końcu:

    W tej chwili twój <script>element jest ładowany do <head>elementu twojego dokumentu. Oznacza to, że zostanie wykonany przed bodyzaładowaniem. Programiści Google zalecają przeniesienie <script>tagów na koniec strony, aby cała zawartość HTML była renderowana przed przetworzeniem kodu 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
Myślę, że jest to dokładniejsze i bardziej aktualne niż zaakceptowana odpowiedź.
— theUtherSide

8

Dodaj swój kod do zdarzenia onload. Przyjęta odpowiedź pokazuje to poprawnie, jednak ta odpowiedź, podobnie jak wszystkie inne w momencie pisania, sugeruje również umieszczenie tagu script po zamykającym tagu body,.

To nie jest prawidłowy kod HTML. Jednak spowoduje to, że Twój kod będzie działał, ponieważ przeglądarki są zbyt miłe;)

Zobacz tę odpowiedź, aby uzyskać więcej informacji. Czy umieszczanie tagu <script> po tagu </body> jest niewłaściwe?

Z tego powodu inne odpowiedzi zostały odrzucone.


4

Lub dodaj tę część

<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>

po kodzie HTML, na przykład:

    <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

Przeglądarka analizuje kod HTML od góry do dołu, a skrypt jest uruchamiany przed załadowaniem treści. Aby naprawić wstawianie skryptu po treści.

  <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 nie jest jeszcze dostępny, gdy działa Twój kod.

Co możesz zamiast tego zrobić:

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

@Jake, czy mógłbyś być bardziej szczegółowy? Jakikolwiek przykład przeglądarki / wersji, w której to nie działa?
— Christophe,

chrome @ 39 i firefox @ 33
— Jake

@Jake ok, więc moja odpowiedź była poprawna w momencie pisania ;-) Dzięki za ostrzeżenie, zrobię kilka testów i opublikuję aktualizację.
— Christophe
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.