整理一下常見(jiàn)的IE錯(cuò)誤
多年以來(lái),IE一直都是最難于調(diào)試JavaScript 錯(cuò)誤的瀏覽器。IE給出的錯(cuò)誤消息一般很短又語(yǔ)焉不詳。而且上下文信息也很少,有時(shí)甚至一點(diǎn)都沒(méi)有。下面幾小節(jié)將分別探討一些在IE中難于調(diào)試的JavaScript 錯(cuò)誤。
操作終止
在IE8 之前的版本中,存在一個(gè)相對(duì)于其他瀏覽器而言,最令人迷惑、討厭,也最難于調(diào)試的錯(cuò)誤:操作終止(operation aborted)。在修改尚未加載完成的頁(yè)面時(shí),就會(huì)發(fā)生操作終止錯(cuò)誤。發(fā)生錯(cuò)誤時(shí),會(huì)出現(xiàn)一個(gè)模態(tài)對(duì)話(huà)框,告訴你“操作終止。"單擊確定(OK) 按鈕,則卸載整個(gè)頁(yè)面,繼而顯示一張空白屏幕;此時(shí)要進(jìn)行調(diào)試非常困難。下面的示例將會(huì)導(dǎo)致操作終止錯(cuò)誤。
<body>
<div>
<script>
document.body.appendChild(document.createElement("div"));
</script>
</div>
</body>
這個(gè)例子中存在的問(wèn)題是:JavaScript代碼在頁(yè)面尚未加載完畢時(shí)就要修改document.body,而且script元素還不是body元素的直接子元素。準(zhǔn)確一點(diǎn)說(shuō),當(dāng)script節(jié)點(diǎn)被包含在某個(gè)元素中,而且JavaScript代碼又要使用appendChi1d、innerHTML或其他DOM 方法修改該元素的父元素或祖先元素時(shí),將會(huì)發(fā)生操作終止錯(cuò)誤(因?yàn)橹荒苄薷囊呀?jīng)加載完畢的元素)。
要避免這個(gè)問(wèn)題,可以等到目標(biāo)元素加載完畢后再對(duì)它進(jìn)行操作,或者使用其他操作方法。例如,為document.body添加一個(gè)絕對(duì)定位在頁(yè)面上的覆蓋層,就是一種非常常見(jiàn)的操作。通常,開(kāi)發(fā)人員都是使用appendChild方法來(lái)添加這個(gè)元素的,但換成使用insertBefore()方法也很容易。因此,只要修改前面例子中的一行代碼,就可以避免操作終止錯(cuò)誤。
<body>
<div>
<script>
document.body.lnsertBefore(document.createElement("div"), document.body.firstChild);
</script>
</div>
</body>
在這個(gè)例子中,新的div元素被添加至document.body的開(kāi)頭部分而不是末尾。因?yàn)橥瓿蛇@一操作所需的所有信息在腳本運(yùn)行時(shí)都是已知的,所以這不會(huì)引發(fā)錯(cuò)誤。
除了改變方法之外,還可以把script元素從包含元素中移出來(lái),直接作為body的子元素。例如:
<body>
<div>
</div>
<script>
document.body.appendChild(document.createElement("div"));
</script>
</body>
這一次也不會(huì)發(fā)生錯(cuò)誤,因?yàn)槟_本修改的是它的直接父元素,而不再是間接的祖先元素。
在同樣的情況下,IE8不再拋出操作終止錯(cuò)誤,而是拋出常規(guī)的JavaScript 錯(cuò)誤,帶有如下錯(cuò)誤消息:
HTML Parsing Error: unable to modify the parent Container element before the child element is closed (KB927917).
不過(guò),雖然瀏覽器拋出的錯(cuò)誤不同,但解決方案仍然是一樣的。
無(wú)效字符
根據(jù)語(yǔ)法,JavaScript 文件必須只包含特定的字符。在JavaScript 文件中存在無(wú)效字符時(shí), IE會(huì)拋出無(wú)效字符( invalid character )錯(cuò)誤。所謂無(wú)效字符,就是JavaScript語(yǔ)法中未定義的字符。例如,有一個(gè)很像減號(hào)但卻由Unicode 值8211 表示的字符( \u2013 ),就不能用作常規(guī)的減號(hào)( ASCII 編碼為45 ),因?yàn)镴avaScript 語(yǔ)法中沒(méi)有定義該字符。這個(gè)字符通常是在Word 文檔中自動(dòng)插入的。如果你的代碼是從Word 文檔中復(fù)制到文本編輯器中,然后又在IE 中運(yùn)行的,那么就可能會(huì)遇到無(wú)效字符錯(cuò)誤。其他瀏覽器對(duì)無(wú)效字符做出的反應(yīng)與IE類(lèi)似,F(xiàn)irefox會(huì)拋出非法字符(iIlegal character) 錯(cuò)誤,Safari會(huì)報(bào)告發(fā)生了語(yǔ)法錯(cuò)誤,而Opera 則會(huì)報(bào)告發(fā)生了ReferenceError (引用錯(cuò)誤)。因?yàn)樗鼤?huì)將無(wú)效字符解釋為未定義的標(biāo)識(shí)符。
未找到成員
IE中的所有DOM對(duì)象都是以COM 對(duì)象,而非原生JavaScript對(duì)象的形式實(shí)現(xiàn)的。這會(huì)導(dǎo)致一些與垃圾收集相關(guān)的非常奇怪的行為。IE中的未找到成員( Member not found )錯(cuò)誤,就是由于垃圾收集例程配合錯(cuò)誤所直接導(dǎo)致的。
具體來(lái)說(shuō),如果在對(duì)象被銷(xiāo)毀之后,又給該對(duì)象賦值,就會(huì)導(dǎo)致未找到成員錯(cuò)誤。而導(dǎo)致這個(gè)錯(cuò)誤的,一定是COM 對(duì)象。發(fā)生這個(gè)錯(cuò)誤的最常見(jiàn)情形是使用event 對(duì)象的時(shí)候。IE中的event對(duì)象是window的屬性,該對(duì)象在事件發(fā)生時(shí)創(chuàng)建,在最后一個(gè)事件處理程序執(zhí)行完畢后銷(xiāo)毀。假設(shè)你在一個(gè)閉包中使用了event 對(duì)象,而該閉包不會(huì)立即執(zhí)行,那么在將來(lái)調(diào)用它并給event 的屬性賦值時(shí),就會(huì)導(dǎo)致未找到成員錯(cuò)誤,如下面的例子所示。
document.onclick = function () {
var event = window.event;
setTimeout(function (){
event.returnValue = false; //未找到成員錯(cuò)誤
}, 1000);
};
在這段代碼中,我們將一個(gè)單擊事件處理程序指定給了文檔。在事件處理程序中,window.event被保存在event 變量中。然后,傳人setTimeout()中的閉包里又包含了event變量。當(dāng)單擊事件處理程序執(zhí)行完畢后,event 對(duì)象就會(huì)被銷(xiāo)毀,因而閉包中引用對(duì)象的成員就成了不存在的了。換句話(huà)說(shuō),由于不能在COM對(duì)象被銷(xiāo)毀之后再給其成員賦值,在閉包中給returnValue 賦值就會(huì)導(dǎo)致未找到成員錯(cuò)誤。
未知運(yùn)行時(shí)錯(cuò)誤
當(dāng)使用innerHTML或outerHTML以下列方式指定HTML時(shí),就會(huì)發(fā)生未知運(yùn)行時(shí)錯(cuò)誤( Unknown runtime error ):一是把塊元素插入到行內(nèi)元素時(shí), 二是訪(fǎng)問(wèn)表格任意部分( table 、 tbody等)的任意屬性時(shí)。例如,從技術(shù)角度說(shuō),span標(biāo)簽不能包含div之類(lèi)的塊級(jí)元素,因此下面的代碼就會(huì)導(dǎo)致未知運(yùn)行時(shí)錯(cuò)誤:
span.innerHTML = "div Hi /div"; //這里,span包含了div元素
在遇到把塊級(jí)元素插入到不恰當(dāng)位置的情況時(shí),其他瀏覽器會(huì)嘗試糾正并隱藏錯(cuò)誤,而IE在這一點(diǎn)上反倒很較真兒。
語(yǔ)法錯(cuò)誤
通常,只要IE一報(bào)告發(fā)生了語(yǔ)法錯(cuò)誤( syntax error ),都可以很快找到錯(cuò)誤的原因。這時(shí)候,原因可能是代碼中少了一個(gè)分號(hào),或者花括號(hào)前后不對(duì)應(yīng)。然而,還有一種原因不十分明顯的情況需要格外注意。
如果你引用了外部的JavaScript 文件,而該文件最終并沒(méi)有返回JavaScript代碼,IE也會(huì)拋出語(yǔ)法錯(cuò)誤。例如,script元素的src特性指向了一個(gè)HTML文件,就會(huì)導(dǎo)致語(yǔ)法錯(cuò)誤。報(bào)告語(yǔ)法錯(cuò)誤的位置時(shí),通常都會(huì)說(shuō)該錯(cuò)誤位于腳本第一行的第一個(gè)字符處。Opera 和Safari 也會(huì)報(bào)告語(yǔ)法錯(cuò)誤,但它們會(huì)給出導(dǎo)致問(wèn)題的外部文件的信息;IE就不會(huì)給出這個(gè)信息,因此就需要我們自己重復(fù)檢查一遍引用的外部JavaScript文件。但Firefox會(huì)忽略那些被當(dāng)作JavaScript 內(nèi)容嵌入到文檔中的非JavaScript文件中的解析錯(cuò)誤。
在服務(wù)器端組件動(dòng)態(tài)生成JavaScript 的情況下,比較容易出現(xiàn)這種錯(cuò)誤。很多服務(wù)器端語(yǔ)言都會(huì)在發(fā)生運(yùn)行錯(cuò)誤時(shí),向輸出中插入HTML代碼,而這種包含HTML的輸出很容易就會(huì)違反JavaScript語(yǔ)法。如果在追查語(yǔ)法錯(cuò)誤時(shí)遇到了麻煩,我們建議你再仔細(xì)檢查一遍引用的外部文件,確保這些文件中沒(méi)有包含服務(wù)器因錯(cuò)誤而插入到其中的HTML。
系統(tǒng)無(wú)法找到指定資源
系統(tǒng)無(wú)法找到指定資源(The system cannot locate the resource specified )這種說(shuō)法,恐陷要算是IE給出的最有價(jià)值的錯(cuò)誤消息了。在使用JavaScript 請(qǐng)求某個(gè)資源URL ,而該URL的長(zhǎng)度超過(guò)了IE 對(duì)URL最長(zhǎng)不能超過(guò)2083個(gè)字符的限制時(shí),就會(huì)發(fā)生這個(gè)錯(cuò)誤。IE不僅限制JavaScript中使用的URL的長(zhǎng)度,而且也限制用戶(hù)在瀏覽器自身中使用的URL長(zhǎng)度(其他瀏覽器對(duì)URL 的限制沒(méi)有這么嚴(yán)格)。IE 對(duì)URL路徑還有一個(gè)不能超過(guò)2048個(gè)字符的限制。下面的代碼將會(huì)導(dǎo)致錯(cuò)誤。
function createLongUrl(url){
var s = "?";
for (var i=0, len= 2500; i < len; i++){
s += "a" ;
}
return url + s;
}
var x = new XMLHttpRequest( );
x.open("get", createLongUrl("http://www.somedomain.com/"), true);
x.send(null);
在這個(gè)例子中,XMLHttpRequest對(duì)象試圖向一個(gè)超出最大長(zhǎng)度限制的URL發(fā)送請(qǐng)求。在調(diào)用open()方法時(shí),就會(huì)發(fā)生錯(cuò)誤。避免這個(gè)問(wèn)題的辦法,無(wú)非就是通過(guò)給查詢(xún)字符參數(shù)起更短的名字,或者減少不必要的數(shù)據(jù),來(lái)縮短查詢(xún)字符串的長(zhǎng)度。另外,還可以把請(qǐng)求方法改為POST,通過(guò)請(qǐng)求體而不是查詢(xún)字符串來(lái)發(fā)送數(shù)據(jù)。
相關(guān)文章
JS中touchstart事件與click事件沖突的解決方法
這篇文章主要給大家介紹了關(guān)于JS中touchstart事件與click事件沖突的解決方法,文中通過(guò)示例代碼將解決的方法介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2018-03-03
深入理解JavaScript系列(35):設(shè)計(jì)模式之迭代器模式詳解
這篇文章主要介紹了深入理解JavaScript系列(35):設(shè)計(jì)模式之迭代器模式詳解,迭代器模式(Iterator):提供一種方法順序一個(gè)聚合對(duì)象中各個(gè)元素,而又不暴露該對(duì)象內(nèi)部表示,需要的朋友可以參考下2015-03-03
關(guān)于JavaScript中的this指向問(wèn)題總結(jié)篇
在小編面試過(guò)程中經(jīng)常會(huì)遇到j(luò)avascript中this指向問(wèn)題,可以說(shuō)是前端面試必問(wèn),下面小編給大家總結(jié)了一下js中this的指向,感興趣的朋友一起學(xué)習(xí)吧2017-07-07
JavaScript實(shí)現(xiàn)動(dòng)態(tài)高度過(guò)渡的3種方式總結(jié)
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)動(dòng)態(tài)高度過(guò)渡的3種方式,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-01-01
JavaScript前端實(shí)現(xiàn)PDF加解密
Dynamsoft?Document?Viewer是一個(gè)用于文檔掃描和查看的JavaScript?SDK,可以在前端對(duì)PDF文件進(jìn)行加密和解密,下面我們就來(lái)看看它的具體使用吧2024-12-12
微信小程序?qū)崿F(xiàn)tab點(diǎn)擊切換
這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)tab點(diǎn)擊切換,不滑動(dòng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07
javascript實(shí)現(xiàn)遮罩層動(dòng)態(tài)效果實(shí)例
這篇文章主要介紹了javascript實(shí)現(xiàn)遮罩層動(dòng)態(tài)效果,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05
JavaScript的設(shè)計(jì)模式經(jīng)典之建造者模式
建造者模式是設(shè)計(jì)模式的一種,將一個(gè)復(fù)雜對(duì)象的構(gòu)建與它的表示分離,使得同樣的構(gòu)建過(guò)程可以創(chuàng)建不同的表示。接下來(lái)通過(guò)本文給大家介紹JavaScript的設(shè)計(jì)模式經(jīng)典之建造者模式,感興趣的朋友一起學(xué)習(xí)吧2016-02-02

