作者:elcarim的部落格
網址:http://www.cnblogs.com/elcarim5efil/p/4749262.html
document.write的用處
document.write是JavaScript中對document.open所開啟的檔案流(document stream操作的API方法,它能夠直接在檔案流中寫入字串,一旦檔案流已經關閉,那document.write就會重新利用document.open開啟新的檔案流並寫入,此時原來的檔案流會被清空,已渲染好的頁面就會被清除,瀏覽器將重新構建DOM並渲染新的頁面。
寫入文字
下麵來看看如何在利用document.write來寫入指令碼。先考慮如下程式碼:
Head
');我們將程式碼作出上面的改動,意圖在利用document.write在頁面中插入一段指令碼。這段程式碼的本意是彈出一個視窗,阻塞瀏覽器對HTML的解析。
瀏覽器下掃清頁面,發現並不管用,取而代之的是顯示出一個沒有意料到的頁面。
Head
');
Tail
去檢查DOM樹,就會發現,這段指令碼被攔腰截斷了!瀏覽器將它解析成以下程式碼:
document.write('
');
插入文字中的
被當成了第一個script的閉合標簽,因此這個段程式碼成了非法程式碼,因為document.write的呼叫書寫不正確,缺少右邊的括號)。此時,你可以在console中看到相關的錯誤資訊。
為瞭解決這個問題,我們可以對插入文字中閉合的的標簽進行輕微修改,對最後一個>進行轉義,變成\>。
此時再掃清一下頁面,就可以看到預想中的結果。即頁面中僅顯示h1,彈窗阻塞了瀏覽器對HTML的解析,關閉彈窗後,瀏覽器繼續對HTML的解析並完成對頁面的渲染。
再去看看DOM的結構,會發現在原有的script元素後面又多了一個新的
對之前的程式碼作簡單修改,這段程式碼同樣是想插入一個p元素,但它是在5秒以後才執行。
掃清頁面後,我們看到了這樣的顯示效果:
Head
Tail
但是5秒以後,頁面卻變成了這樣:
5 secs later
原來的h1、h2甚至是script,DOCTYPE還有head(當然,之前並沒有往head新增任何標簽,但如果添加了,這些標簽也會有同樣的下場),它們全部都不見了,取而代之的是一個基本的html結構,它是這樣的:
5 secs later
這是一個全新的頁面,document.write將之前的頁面全部清除了,重新開啟一頁面併在這個頁面上寫入了新的標簽。為什麼會這樣呢?
回到再文章開頭所描述文字,就會找到結果。這是因為,5秒以後,瀏覽器早已完成了HTML的解析,並將檔案流給關閉了。5秒後,timeout事件觸發,document.write在執行的時候發現檔案流已經關閉了,就會重新呼叫document.open開啟一個新的檔案流,而document.open的呼叫則會清除已有的檔案。所以,最終看到的顯示結果就是向上面那樣,之前存在的頁面都被清除掉了。
如果我們把document.write呼叫放到DOMCOntentLoaded或load的事件處理中,也會得到同樣的結果。
這樣看到,除非是在瀏覽器關閉檔案之前呼叫document.write,否則當前頁面都會被清除。
這一個特性決定了document.write在實際開發中的應用範圍和時機。那麼,什麼時候應該使用document.write呢?
在網上搜集的資料看,一般在下列情景下可以利用document.write來完成某些特殊的操作:
載入需要配合JS指令碼使用的外部CSS檔案
利用下麵的陳述句載入外部樣式檔案:
document.write(' ');
將所有需要用到JS的樣式都放到這個外部樣式表中,如果瀏覽器不禁用JS,那麼該樣式表就會被順利載入,否則頁面就不會使用該樣式。(Don’t docwrite scripts)
在新的視窗中寫入新的頁面資料時
既然在一個已載入完成的頁面中呼叫document.write會重寫整個頁面,那麼在一個新的視窗的空白頁面中呼叫這個方法,就不存在這樣的的問題了。
另外,在呼叫document.write,最好不要把document.open和document.close漏掉,儘管多數時候瀏覽器會幫忙完成這些操作。即,一個標準的document.write應該是這樣的:
document.open();
document.write('anthing')
document.close();
弊端
從某個角度說,document.write的實際功能確實很強,能夠直接修改檔案流,但它有很多弊端:
- 在非loading階段呼叫document.write會清除已載入的頁面;
- document.write不能夠在XHTML中使用;
- 嵌入script中的document.write不能給任意節點新增子節點,因為它是隨著DOM的構建執行的;
- 利用document.write寫入HTML字串流並不是一個好方法,它有違DOM操作的概念;
- 利用document.write新增script載入外部指令碼時,瀏覽器的HTML解析會被script的載入所阻塞;
總結
綜合上面所描述的關於document.write的種種特點,個人感覺還是不到迫不得已的時候,不要去使用document.write,使用不當document.write不僅會影響頁面的效能,還容易造成各種bug。
要對DOM進行操作時,還是應當使用安全且對DOM的友好的API方法,以避免不必要的問題出現。
上述資訊都是以自己做的小測試和網上的參考資料為基礎總結出來,有錯誤的地方,歡迎大家指出,我會儘快作出修正。
參考
- js中document.write的那點事
- document.wrtie_MDN
- Three JavaScript articles and one best practice
- Don’t docwrite scripts
- Why is document.write considered a “bad practice”?