เหตุใด document.body จึงเป็นโมฆะในจาวาสคริปต์ของฉัน


132

นี่คือเอกสาร HTML สั้น ๆ ของฉัน

เหตุใด Chrome Console จึงสังเกตข้อผิดพลาดนี้:

"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
John Hoffman

คำตอบ:


180

ตอนนี้ยังไม่ได้กำหนดร่างกาย โดยทั่วไปคุณต้องการสร้างองค์ประกอบทั้งหมดก่อนที่จะรันจาวาสคริปต์ที่ใช้องค์ประกอบเหล่านี้ ในกรณีนี้คุณมีจาวาสคริปต์ในบางส่วนที่ใช้head bodyไม่เท่.

คุณต้องการที่จะห่อรหัสนี้ในwindow.onloadการจัดการหรือวางไว้หลังจาก<body>แท็ก (ดังกล่าวโดยE-บาเจาะ 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
หน้าจะอ่านจากบนลงล่างและจาวาสคริปต์จะดำเนินการไปพร้อมกัน คุณมีจาวาสคริปต์บางส่วนในheadส่วนที่กำลังดำเนินการ แต่bodyบางส่วนของ html อาจจะยังไม่ได้ดาวน์โหลด หรือดาวน์โหลดแล้ว แต่ยังไม่ได้รับการประเมินในตอนนี้ ดังนั้นจึงไม่มีอยู่ใน DOM
Sergio Tulentsev

3
จะเกิดอะไรขึ้นถ้าคุณไม่ต้องการแทนที่ onload ที่มีอยู่ซึ่งกำหนดไว้ในไฟล์อื่น?
Tom Brito

1
@TomBrito: "หรือวางไว้หลังจาก<body>แท็ก"
เซร์คิโอ Tulentsev

1
ช้าไปหน่อย แต่ยังสามารถใช้ addEventListener เพื่อแนบ Listener เข้ากับหน้าต่างโดยไม่ต้องแทนที่สิ่งที่มีอยู่
edvilme

36

สคริปต์ของคุณกำลังดำเนินการก่อนที่bodyองค์ประกอบจะโหลด

มีสองวิธีในการแก้ปัญหานี้

  • รวมรหัสของคุณใน DOM Load callback:

    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

เพิ่มรหัสของคุณในเหตุการณ์ onload คำตอบที่ยอมรับจะแสดงสิ่งนี้อย่างถูกต้องอย่างไรก็ตามคำตอบนั้นรวมถึงคำตอบอื่น ๆ ทั้งหมดในขณะที่เขียนยังแนะนำให้ใส่แท็กสคริปต์ไว้หลังแท็กเนื้อหาปิดด้วย

นี่ไม่ใช่ 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);

@ เจคคุณสามารถเจาะจงมากขึ้นได้ไหม? ตัวอย่างเบราว์เซอร์ / เวอร์ชันใดที่ใช้งานไม่ได้
Christophe

chrome @ 39 และ firefox @ 33
Jake

@Jake ok ดังนั้นคำตอบของฉันจึงถูกต้องในขณะที่เขียน ;-) ขอบคุณที่แจ้งเตือนฉันฉันจะทำการทดสอบบางอย่างและฉันจะโพสต์การอัปเดต
Christophe
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.