Чому document.body в моєму JavaScript не входить?


132

Ось мій короткий HTML-документ.

Чому консоль Chrome відзначає цю помилку:

"Uncaught TypeError: Неможливо викликати метод 'appendChild' з 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>

Я використовую Google Chrome.
Джон Гофман

Відповіді:


180

Тіло на даний момент ще не визначено. Загалом, ви хочете створити всі елементи, перш ніж виконувати javascript, який використовує ці елементи. У цьому випадку у headрозділі, який використовується, у вас є javascript body. Не круто.

Ви хочете , щоб обернути цей код в window.onloadобробник або помістити його після того, як в <body>тезі (як уже згадувалося електронної 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>

Дивіться демонстрацію .


1
Дякую, що ти маєш на увазі? У мене немає тегу тіла?
Джон Гофман

5
Сторінка читається зверху вниз, а по дорозі виконується javascript. У headрозділі, який виконується, у вас є javascript . Але body, можливо, частина html ще не завантажена. Або завантажується, але це все ще не оцінюється на даний момент. Тож його не існує в DOM.
Серхіо Туленцев

3
Що робити, якщо ви не хочете замінити існуючий навантаження, визначений в іншому файлі?
Том Бріто

1
@TomBrito: «або помістити його після того, як в <body>тезі»
Серхіо Tulentsev

1
Трохи пізно, але також можна використовувати addEventListener для приєднання слухача до вікна, не замінюючи існуючих.
edvilme

36

Ваш сценарій виконується до того, як bodyелемент навіть завантажився.

Є кілька способів вирішити це.

  • Оберніть свій код у зворотній зв'язок DOM Load call:

    Введіть свою логіку в слухача подій DOMContentLoaded.

    При цьому зворотний виклик буде виконуватися, коли bodyелемент завантажився.

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

    Залежно від ваших потреб, ви можете альтернативно приєднати loadслухач події до windowоб'єкта:

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

    Про різницю між подіями DOMContentLoadedта loadподіями див. Це питання .

  • Перемістіть позицію свого <script>елемента та завантажте останній JavaScript:

    Зараз ваш <script>елемент завантажується в <head>елемент вашого документа. Це означає, що він буде виконаний до bodyзавантаження. Розробники Google рекомендують перемістити <script>теги до кінця вашої сторінки, щоб весь вміст HTML виводився до обробки 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
Я думаю, що це більш ретельне та актуальне, ніж прийнята відповідь.
theUtherSide

8

Додайте свій код до події завантаження. Прийнята відповідь показує це правильно, проте ця відповідь, як і всі інші під час написання, також пропонують помістити тег скрипту після закриття тегу body,.

Це неправда html. Однак це призведе до роботи вашого коду, оскільки браузери занадто добрі;)

Дивіться цю відповідь для отримання додаткової інформації Чи неправильно розміщувати тег <script> після тега </body>?

З цієї причини відмовилися від інших відповідей.


4

Або додайте цю частину

<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, наприклад:

    <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

Браузер аналізує ваш HTML зверху вниз, ваш сценарій працює перед завантаженням тіла. Для виправлення ставимо сценарій після тіла.

  <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 ще не доступний, коли ваш код працює.

Що можна зробити замість цього:

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

@Jake Ви могли б бути більш конкретними? Будь-який приклад браузера / версії, де він не працює?
Крістоф

chrome @ 39 та firefox @ 33
Jake

@Jake нормально, тому моя відповідь була правильною на момент написання ;-) Дякую, що попередили мене, я проведу тестування, і я опублікую оновлення.
Крістоф
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.