使用$ .each()迭代document.styleSheets时无效的过程调用或参数IE问题

Rob*_*nik 3 javascript each internet-explorer-8 jquery-1.3.2

我编写了这段代码,它遍历所有全局样式表规则并将它们存储在数组/对象中.我稍后使用这个类似字典的对象来更改全局规则,而不是在单个元素上设置样式.

在IE8中执行代码中断,但在Firefox3.7和Chrome4中工作正常.

var allRules;

$(function() {
    var fileRules;
    allRules = [];
    $.each(document.styleSheets, function() {
        // get rules for any browser (IE uses rules array)
        fileRules = this.cssRules || this.rules;
        $.each(fileRules, function() {
            allRules[this.selectorText] = this;
        });
    });
});
Run Code Online (Sandbox Code Playgroud)

我收到Invalid procedure call or argument错误.当我尝试调试它时,这段代码成功迭代了两个带有规则的CSS样式表文件,但是当第二个迭代完成后,它就失败了.

我似乎无法在此代码中找到错误.

Rob*_*nik 13

问题

经过彻底的测试后,我发现document.styleSheetsIE不是常规数组.这就是它$.each()到达终点时打破电话的原因.

如果我们看看jQuery函数本身,它有一个for循环迭代一个具有length属性的对象,错误地认为它是一个数组.document.styleSheets确实length有财产,但它显然不是一个数组.所以当执行这个for循环时$.each():

for (var value = object[0];
     i < length && callback.call( value, i, value ) !== false;
     value = object[++i]){}
Run Code Online (Sandbox Code Playgroud)

迭代完最后一个元素后失败.正如我们所看到的,这个for循环不会自行增加i,而是在为其分配新值时递增它value.

我们也可以手动检查.在任何浏览器的地址栏中写下这两行:

javascript:var a=[1,2,3];alert(a[3]);void(0);
javascript:alert(document.styleSheets[document.styleSheets.length]);void(0);
Run Code Online (Sandbox Code Playgroud)

第一个在所有浏览器中运行良好,但第二个在IE中失败.

解决方案

我们必须在样式表上重写迭代

var allRules;

$(function() {
    var fileRules;
    allRules = {};
    // can't use $.each() over document.styleSheets because it's not an array in IE
    for (var i = 0; i < document.styleSheets.length; i++)
    {
        fileRules = document.styleSheets[i].cssRules || document.styleSheets[i].rules;
        $.each(fileRules, function() {
            allRules[this.selectorText] = this;
        });
    }
});
Run Code Online (Sandbox Code Playgroud)