某台機器上IE8拋“Invalid procedure call or argument”異常


某台機器上,訪問公司的好幾個產品網站,都拋出很多“Invalid procedure call or argument”,跟進了下,情況最后簡化為:

1. 環境:

browser_info:"platform:Win32;msie;version:8.0;ie",
navigator:"appCodeName:Mozilla;appName:Microsoft Internet Explorer;appMinorVersion:Release Candidate 1;cpuClass:x86;platform:Win32;systemLanguage:zh-cn;userLanguage:zh-cn;appVersion:4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident\u002F4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729);userAgent:Mozilla\u002F4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident\u002F4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729);onLine:true;cookieEnabled:true"

 

2. 錯誤代碼:

<!DOCTYPE html><html><head></head>
<body><div></div></body>
<script>
alert(document.body.querySelectorAll);
var els = document.body.querySelectorAll('div');
alert(els[2]);// 2 > els.length-1
</script>
</html>

 

3. 原因分析:

以上代碼中,els是一個querySelectorAll的結果。els[2]會拋異常,而不是返回undefined.

 

4. QWrap代碼錯誤點:在QWrap的selector里,有可能會出現對querySelectorAll結果取下標超界。參見以下代碼的紅色部分

    /*
    * nativeQuery(refEl,sSelector): 如果有原生的querySelectorAll,並且只是簡單查詢,則調用原生的query,否則返回null. 
    * @param {Element} refEl 參考元素
    * @param {string} sSelector selector字符串
    * @returns 
    */
    function nativeQuery(refEl, sSelector) {
        if (hasNativeQuery && /^((^|,)\s*[.\w-][.\w\s\->+~]*)+$/.test(sSelector)) {
            //如果瀏覽器自帶有querySelectorAll,並且本次query的是簡單selector,則直接調用selector以加速
            //部分瀏覽器不支持以">~+"開始的關系運算符
            var oldId = refEl.id,
                tempId,
                arr = [],
                els;
            if (!oldId && refEl.parentNode) { //標准的querySelectorAll中的selector是相對於:root的,而不是相對於:scope的
                tempId = refEl.id = '__QW_slt_' + nativeQueryStamp++;
                try {
                    els = refEl.querySelectorAll('#' + tempId + ' ' + sSelector);
                } finally {
                    refEl.removeAttribute('id');
                }
            }
            else{
                els = refEl.querySelectorAll(sSelector);
            }
            for (var i = 0, elI; elI = els[i++];) arr.push(elI);
            return arr;
        }
        return null;
    }

 

5. 反思:

  代碼A:for (var i = 0, len = els.length; i < len; i++) arr.push(els[i]);

  代碼B:for (var i = 0, elI; elI = els[i++];) arr.push(elI);

用“代碼B”代替“代碼A”是一種常見寫法,可是,碰到這台機器,卻冏冏冏冏冏冏冏冏冏了。

 

6. 問題修復:

     老老實實的改回代碼A。OK了。

 

7. 延伸:

“下標超界拋異常,而不是返回undefined”這個坑好冏。。。

貌似那同學的機器訪問淘寶頁面,也有類似異常拋出,不知是否是同樣原因。友情@淘寶同學一下。

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM