【问题标题】:Invalid procedure call or argument IE issue when iterating through document.styleSheets using $.each()使用 $.each() 遍历 document.styleSheets 时出现无效的过程调用或参数 IE 问题
【发布时间】:2011-01-18 09:56:57
【问题描述】:

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

以下代码在 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;
        });
    });
});

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

我似乎在这段代码中找不到错误。

【问题讨论】:

  • 由于您没有将allRules 用作数组,因此您应该将其声明为对象:allRules = {};
  • @Tim Down:也试过了,但也没用。
  • 对不起,我应该说它不会解决任何问题。这只是一个旁白。

标签: javascript internet-explorer-8 each jquery-1.3.2


【解决方案1】:

代码正确的是:

var fileRules;
(function ($) {
    allRules = {};
    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;
        })(jQuery);
    }
});

【讨论】:

  • 这段代码肯定行不通……抱歉。您将(jQuery) 添加到$.each... 为什么首先添加它?您可能想让 main 函数立即可执行。但即使......那么这段代码应该运行在文档中的最后一个。通过在准备好的文档上运行它来使用解决方案的方法更加透明。你不这么认为吗?
  • 更不用说你已经将allRules 设为闭包变量,所以你将无法访问你读过的那些规则......
【解决方案2】:

问题

经过彻底的测试,我发现document.styleSheets 不是IE 中的常规数组。这就是为什么它在到达结尾时中断$.each() 调用。

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

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

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

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

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

第一个在所有浏览器中运行良好,但第二个在 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;
        });
    }
});

【讨论】:

  • 有关问题和解决方案的出色文档。 +1
  • @Greg:我认为它可能对其他人也有用,所以我更彻底地记录了它。感谢您的支持。
【解决方案3】:

会不会是解析规则本身失败了?尝试使用不同的样式表并重新排序规则,以确保解析规则不会因某种原因出现问题。

【讨论】:

  • 但我没有以任何方式解析规则...我只是存储他们的名称和规则...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多