JavaScriptでdocument.bodyがnullになるのはなぜですか?


132

これが私の簡単なHTML文書です。

Chromeコンソールでこのエラーが表示されるのはなぜですか:

"キャッチされていない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を使用しています。
John Hoffman、

回答:


180

ボディはこの時点ではまだ定義されていません。一般に、これらの要素を使用するJavaScriptを実行する前に、すべての要素を作成する必要があります。この場合、headを使用するセクションにjavascriptがありますbody。クールではありません。

このコードをwindow.onloadハンドラーでラップするか、タグの後に配置します<body>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>

デモを参照してください


1
ありがとう、どういう意味ですか?本文タグはありませんか?
John Hoffman、

5
ページは上から下に読み込まれ、JavaScriptが途中で実行されます。head実行中のセクションにJavaScriptがあります。しかしbody、htmlの一部は、おそらくまだダウンロードされていません。またはダウンロードされましたが、現時点ではまだ評価されていません。そのため、DOMには存在しません。
Sergio Tulentsev 2012年

3
別のファイルで定義された既存のonloadを上書きしたくない場合はどうなりますか?
トムブリト2013年

1
@TomBrito:「や場所、それを後に<body>タグ」
セルジオTulentsev

1
少し遅れますが、addEventListenerを使用して、既存のリスナーを置き換えることなく、リスナーをウィンドウにアタッチすることもできます。
edvilme

36

body要素が読み込まれる前にスクリプトが実行されています。

これを回避するにはいくつかの方法があります。

  • コードをDOM Loadコールバックでラップします。

    のイベントリスナーでロジックをラップしますDOMContentLoaded

    その際、body要素が読み込まれたときにコールバックが実行されます。

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

    必要に応じて、代わりにloadイベントリスナーをwindowオブジェクトにアタッチできます。

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

    DOMContentLoadedloadイベントの違いについては、この質問を参照してください

  • <script>要素の位置を移動し、最後にJavaScriptをロードします。

    現在、<script>要素は<head>ドキュメントの要素に読み込まれています。つまり、bodyがロードされる前に実行されます。Google開発者<script>は、JavaScriptが処理される前にすべてのHTMLコンテンツがレンダリングされるように、タグをページの最後に移動することをお勧めします。

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

8

コードをonloadイベントに追加します。受け入れられた回答はこれを正しく示していますが、その回答および執筆時点の他のすべての回答は、スクリプトの終了タグをbodyタグの後に置くことも推奨しています。

これは有効なhtmlではありません。ただし、ブラウザが親切すぎるため、コードが機能します;)

詳細については、この回答を参照してください。 <body>タグの後に<script>タグを配置するのは間違っていますか?

このため、他の回答に反対票を投じました。


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

@ジェイク、もっと具体的に教えてもらえますか?動作しないブラウザ/バージョンの例はありますか?
クリストフ

chrome @ 39とfirefox @ 33
Jake

@ジェイク大丈夫、私の回答は執筆の時点では正しかった;-)警告を送ってくれてありがとう。私はいくつかのテストを行い、アップデートを投稿します。
クリストフ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.