Tại sao document.body null trong javascript của tôi?


132

Đây là tài liệu HTML ngắn gọn của tôi.

Tại sao Bảng điều khiển Chrome nhận thấy lỗi này:

"Uncaught TypeError: Không thể gọi phương thức 'appendChild' của 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>

Tôi đang sử dụng Google Chrome.
John Hoffman

Câu trả lời:


180

Cơ thể chưa được xác định tại thời điểm này. Nói chung, bạn muốn tạo tất cả các yếu tố trước khi bạn thực thi javascript sử dụng các yếu tố này. Trong trường hợp này, bạn có một số javascript trong headphần sử dụngbody . Không mát mẻ.

Bạn muốn quấn mã này trong một window.onloadhandler hoặc đặt nó sau khi các <body>thẻ (như đã đề cập bởi 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>

Xem bản demo .


1
Cảm ơn bạn, ý của bạn là gì? Tôi không có thẻ cơ thể?
John Hoffman

5
Trang này được đọc từ trên xuống dưới và javascript được thực thi trên đường đi. Bạn có một số javascript trong headphần đang được thực thi. Nhưng bodymột phần của html, có lẽ, thậm chí chưa được tải xuống. Hoặc nó được tải xuống, nhưng nó vẫn chưa được đánh giá tại thời điểm này. Vì vậy, nó không tồn tại trong DOM.
Sergio Tulentsev

3
Điều gì xảy ra nếu bạn không muốn ghi đè một tải hiện có được xác định trong tệp khác?
Tom Brito

1
@TomBrito: "hoặc đặt nó sau các <body>tag"
Sergio Tulentsev

1
Hơi muộn một chút, nhưng cũng có thể sử dụng addEventListener để gắn trình nghe vào cửa sổ, mà không thay thế những cái hiện có.
edvilme

36

Kịch bản của bạn đang được thực thi trước body phần tử thậm chí được tải.

Có một vài cách để khắc phục điều này.

  • Gói mã của bạn trong một cuộc gọi lại tải DOM:

    Bao bọc logic của bạn trong một trình lắng nghe sự kiện cho DOMContentLoaded .

    Khi làm như vậy, cuộc gọi lại sẽ được thực hiện khi bodyphần tử đã được tải.

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

    Tùy thuộc vào nhu cầu của bạn, bạn có thể đính kèm một trình loadlắng nghe sự kiện vào windowđối tượng:

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

    Để biết sự khác biệt giữa DOMContentLoadedloadcác sự kiện, xem câu hỏi này .

  • Di chuyển vị trí của <script>phần tử của bạn và tải JavaScript cuối cùng:

    Ngay bây giờ, <script>phần tử của bạn đang được tải trong <head>phần tử của tài liệu của bạn. Điều này có nghĩa là nó sẽ được thực thi trước khi bodytải. Các nhà phát triển của Google khuyên bạn nên di chuyển các <script>thẻ đến cuối trang để tất cả nội dung HTML được hiển thị trước khi JavaScript được xử lý.

    <!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
Tôi nghĩ rằng điều này là kỹ lưỡng và hiện tại hơn câu trả lời được chấp nhận.
theStherSide

8

Thêm mã của bạn vào sự kiện onload. Câu trả lời được chấp nhận cho thấy điều này một cách chính xác, tuy nhiên câu trả lời đó cũng như tất cả các câu trả lời khác tại thời điểm viết cũng đề nghị đặt thẻ script sau thẻ thân đóng ,.

Đây không phải là html hợp lệ. Tuy nhiên, nó sẽ khiến mã của bạn hoạt động, vì các trình duyệt quá tử tế;)

Xem câu trả lời này để biết thêm thông tin Có sai không khi đặt thẻ <script> sau thẻ </ body>?

Đánh giá thấp câu trả lời khác cho lý do này.


4

Hoặc thêm phần này

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

sau HTML, như:

    <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

Trình duyệt phân tích cú pháp html của bạn từ trên xuống, tập lệnh của bạn chạy trước khi phần thân được tải. Để sửa tập lệnh đặt sau cơ thể.

  <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 chưa có sẵn khi mã của bạn chạy.

Thay vào đó, bạn có thể làm gì:

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

@Jake bạn có thể cụ thể hơn? Bất kỳ ví dụ nào về trình duyệt / phiên bản không hoạt động?
Barshe

chrome @ 39 và firefox @ 33
Jake

@Jake ok, vì vậy câu trả lời của tôi là chính xác tại thời điểm viết ;-) Cảm ơn đã thông báo cho tôi, tôi sẽ thực hiện một số thử nghiệm và tôi sẽ đăng cập nhật.
Christophe
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.