Неверный вызов процедуры или проблема с аргументом IE при переборе document.styleSheets с использованием $.each()
-
21-09-2019 - |
Вопрос
Я написал этот код, который перебирает все глобальные правила таблицы стилей и сохраняет их в массиве/объекте.Позже я использую этот объект, похожий на словарь, для изменения глобальных правил, а не для установки стилей для отдельных элементов.
Следующие разрывы кода в 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 с правилами, но когда вторая итерация завершается, происходит сбой.
Кажется, я не могу найти ошибку в этом коде.
Решение
Проблема
После тщательного тестирования я выяснил, что document.styleSheets
не является обычным массивом в IE.Вот почему он врывается $.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]){}
он терпит неудачу после повторения последнего элемента.Как мы можем видеть это 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;
});
}
});
Другие советы
Может быть, само правило синтаксического анализа не работает?Попробуйте поэкспериментировать с различными таблицами стилей и изменить порядок правил, чтобы по какой-либо причине не возникло проблем с анализом правила.
код true:
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);
}
});