document.write vs document.getElementById
document.write:
JavaScript中對document.open
所開啟的文件流(document stream操作的API方法,它能夠直接在文件流中寫入字串,一旦文件流已經關閉,那document.write
就會重新利用document.open
開啟新的文件流並寫入,此時原來的文件流會被清空,已渲染好的頁面就會被清除,瀏覽器將重新構建DOM並渲染新的頁面。
一.寫入文字(頁面載入中可以寫入,而不會出現重寫頁面問題)
利用document.write
來寫入指令碼,先考慮如下程式碼:
1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 </head> 5 <body> 6 <h1>Head</h1> 7 <script> 8 document.write('<p>hello document</p>'); 9 </script> 10 <h2>Tail</h2> 11 </body> 12 </html>
這段在h1
和h2
之間內嵌一個指令碼,使用document.write
p
標籤。重新整理頁面,可以看到最終的結果是:
Head
hello document
Tail
即要文字在指令碼執行的位置被插入。這是因為,瀏覽器就解析HTML構建DOM的時候,如果遇到script
就會暫停下來,解析script
中的程式碼並執行,然後再繼續解析剩餘HTML。(阻塞進行的)此時再去瀏覽器中檢測DOM的結構,會發現script
與h2
之間多了一個p
,瀏覽器在解析完h1
之後,碰到script
並執行之,此時document.write
將一段HTML程式碼寫入到文件流中,script執行完畢後,瀏覽器會解析文件流中的字串,對新新增的p
標籤進行解析。如果將渲染好的頁面儲存下來,不同的瀏覽器會有不同的結果。如Chrome和Firefox的做儲存下來的頁面檔案中,script
p
標籤,而IE中則是維持原狀。(這裡指的是原有的HTML結構,不同瀏覽器將頁面儲存會作不同的處理,有些會增加一些不影響原有結構的標籤或註釋。這意味著,如果瀏覽器重新載入Chrome或Firefox中儲存下來的頁面檔案,就會多出一個p
標籤。
二.寫入指令碼(注意加轉義符號)
既然document.write
可以寫入p
並被瀏覽器解析,那麼自然地也可以寫入script
標籤。
<script> document.write('<script>alert("oops!!!")</script>'); </script>
將程式碼作出上面的改動,意圖在利用document.write
在頁面中插入一段指令碼。這段程式碼的本意是彈出一個視窗,阻塞瀏覽器對HTML的解析。瀏覽器下重新整理頁面,發現並不管用,取而代之的是顯示出一個沒有意料到的頁面。
1 Head 2 3 '); 4 Tail
去檢查DOM樹,就會發現,這段指令碼被攔腰截斷了!瀏覽器將它解析成以下程式碼:
1 <script> 2 document.write('<script>alert("oops!!!") 3 </script> 4 ');
插入文字中的</script>
被當成了第一個script
的閉合標籤,因此這個段程式碼成了非法程式碼,因為document.write
的呼叫書寫不正確,缺少右邊的括號)
。此時,你可以在console中看到相關的錯誤信息。(控制檯)解決這個問題,我們可以對插入文字中閉合的的標籤進行輕微修改,對最後一個>
進行轉義,變成\>
。此時再重新整理一下頁面,就可以看到預想中的結果。即頁面中僅顯示h1
,彈窗阻塞了瀏覽器對HTML的解析,關閉彈窗後,瀏覽器繼續對HTML的解析並完成對頁面的渲染。再去看看DOM的結構,會發現在原有的script
元素後面又多了一個新的<script>
元素,其中所執行的程式碼就是我們的alert("opps!!!")
。
弊端
從某個角度說,document.write
的實際功能確實很強,能夠直接修改文件流,但它有很多弊端:
在非loading階段呼叫document.write
會清除已載入的頁面;
document.write不能夠在XHTML中使用;
嵌入script
中的document.write
不能給任意節點新增子節點,因為它是隨著DOM的構建執行的;
利用document.write
寫入HTML字串流並不是一個好方法,它有違DOM操作的概念;
利用document.write
新增script
載入外部指令碼時,瀏覽器的HTML解析會被script
的載入所阻塞;
document.getElementById:
document.getElementById(" ") 得到的是一個物件,用 alert 顯示得到的是“ object ”,而不是具體的值,它有 value 和 length 等屬性,加上 .value 得到的才是具體的值!
document 物件
屬性: title ; bgColor ; url; ( 使用: document.title)
方法:
focus:使得元素得到焦點並執行由 onfocus 事件指定的程式碼。
getElementById:獲取對 ID 標籤屬性為指定值的第一個物件的引用。
getElementsByName:根據 NAME 標籤屬性的值獲取物件的集合。
getElementsByTagName:獲取基於指定元素名稱的物件集合。