Знакомство с расширенными возможностями DOM IE9
Для четвертого предварительного выпуска платформы IE9 был значительно перестроен способ, которым подсистема Chakra JavaScript интегрирована в IE. Это перепроектирование, описанное в публикации Dean (Дина), слегка изменяет модель программирования DOM для режима стандартов IE9, обеспечивая ее совместимость с новыми возможностями ECMAScript 5, большую степень взаимодействия с другими браузерами и соответствие новым стандартам (WebIDL).
В этой публикации планируется подробно рассмотреть некоторые из изменений модели программирования. С преимуществами этих усовершенствованных возможностей модели DOM можно ознакомиться в последнем предварительном выпуске платформы. Чтобы подчеркнуть эти изменения, я сошлюсь на демонстрационную страницу усовершенствованных возможностей модели DOM, которая создана для четвертого предварительного выпуска платформы.
В этой демонстрации тестируются 24 возможности, которые разделяются на 4 основные категории:
- наследование объекта модели DOM от собственных объектов JavaScript;
- функциональная согласованность JavaScript с объектами модели DOM;
- программные компоненты с возможностью взаимодействия;
- поддержка нового ECMAScript 5, применяемая к объектам модели DOM.
Первые две категории тесно связаны, поэтому рассмотрим их вместе.
Наследование объекта модели DOM от собственных объектов JavaScript и функциональная согласованность JavaScript с объектами модели DOM.
До IE9 подсистема JavaScript связывалась с моделью DOM посредством механизма классических привязок модели COM. Эти устаревшие привязки допустимы только для примитивного представления объектов и функций модели DOM в подсистеме JavaScript. Следовательно, множество основных функциональных возможностей JavaScript, которые, по ожиданиям разработчиков, должны были быть доступными для всех объектов и функций (включая такие объекты модели DOM, как Window, Document, NodeList и др.), на самом деле были доступны только для собственных объектов JavaScript (таких как Array, Number и пр.).
Стандарт ECMAScript устанавливает основные операции, которые должны работать одинаково во всех объектах JavaScript, но разрешает «базовым объектам» отклонение от этих стандартных установок. Старая подсистема JavaScript в IE воспринимала объекты модели DOM как «базовые объекты», что означает, что основные операции JavaScript, такие как доступ к свойствам, могли вести себя странно. Будучи разрешенным ECMAScript, несогласованное поведение объектов модели DOM и объектов JavaScript создавало трудности отвечающим за них веб-разработчикам.
Например, один из наиболее распространенных вопросов для многих веб-разработчиков состоял в том, почему функции IE DOM возвращались в оператор JavaScript typeof как «объект», а не как «функция» (эта возможность специально проверялась в части #10 демонстрационной версии).
В стандартном режиме IE модель DOM построена как собственные объекты и функции JavaScript, а не как «базовые объекты», что обеспечивает доступность тех функциональных возможностей, которые веб-разработчики ожидают от собственных объектов.
Программные компоненты с возможностью взаимодействия
Третья группа возможностей демонстрирует уникальное поведение модели программирования IE, которое обычно вызывает трудности у веб-разработчиков. Поскольку это поведение существовало только в модели программирования IE, веб-разработчики обнаруживали, что их код не работает одинаково в разных браузерах.
В качестве части новой архитектуры интеграции было удалено множество несоответствий, мешающих одному и тому же скрипту работать одинаково в разных браузерах. Эта модель программирования может привести к тому, что сайты, имеющие специальный код, созданный для IE, в IE9 будут вести себя иначе, чем раньше. Следовательно, имеет смысл описать эти изменения более глубоко.
Функции теперь являются перечисляемыми
В IE8 и более ранних версиях перечисление объекта модели DOM не касалась каких-либо функций-членов объекта модели DOM. В IE9 теперь перечисляются все свойства объекта модели DOM, дескриптор «enumerable» которого установлен в значение «true». (Другими словами, перечисление может быть изменено программно.) Теперь функции являются перечисляемыми по умолчанию для обеспечения совместимости с другими браузерами.
Удален неявный вызов функций
Функции модели DOM в предыдущих версиях IE были довольно нестандартными. Они не только выглядели как typeof объекта, но также сохраняли статическое значение «this», ссылающееся на объект, которому эти функции принадлежат. Следовательно, было возможно кэшировать ссылку на функцию модели DOM и вызывать ее без явной передачи значения «this»:
// Работает в IE8 и предыдущих версиях
// Не работает в IE9 и в других браузерах
var cachedGetElementById = document.getElementById;
cachedGetElementById('value');
В IE9 это теперь будет вызывать исключение, как происходит в других браузерах. В коде, который ранее зависел от этого поведения IE, можно использовать обходной прием «.call»:
// Работает в IE8/IE9 и в других браузерах
// Не работает в IE7 и в предыдущих версиях
var cachedGetElementById = document.getElementById;
cachedGetElementById.call(document, 'value');
В ECMAScript 5 для функций существует метод «bind», позволяющий им не отвергать особенности программирования, ранее поддерживавшиеся IE:
// Исходно работает в IE9 благодаря «привязанному» API ECMAScript 5
var cachedGetElementById = document.getElementById.bind(document);
cachedGetElementById('value');
Поддержка исключений и «константных» свойств модели DOM
В усовершенствованной модели DOM IE9 теперь имеются обусловленные W3C объекты и стандартизованные коды ошибок исключений модели DOM, которые веб-разработчики могут использовать для определения (в целом) природы сбоя API модели DOM. Эти коды обычно сравниваются со строго определенными «константными» свойствами, чтобы повысить удобочитаемость кода:
…
catch(ex) {
if (ex.code == DOMException.INDEX_SIZE_ERR)
…
}
Усовершенствованная модель DOM предоставляет предварительно определенные «константные» свойства, а также архитектуру для вызова и перехвата исключений модели DOM.
Целостное поведение toString
При полной интеграции Chakra и модели DOM в последней отсутствует собственная реализация toString (функции, преобразующей любой объект в строку). Хотя в старой модели DOM реализация toString была аналогична встроенной версии JavaScript, она не была абсолютно такой же и часто приводила к непоследовательным или запутанным результатам. Объекты модели DOM в IE9 теперь наследуют и используют встроенную в JavaScript функцию toString для получения стандартного результата.
Разделение хранилища свойств и атрибутов
В предыдущей архитектуре объекты модели DOM имели свое собственное хранилище свойств. Это хранилище свойств совпадало с расположением хранилища для атрибутов (которые можно найти в разметке HTML). В новой архитектуре IE9 хранилище атрибутов элементов отделено от динамических свойств, назначаемых объекту скрипта элемента. Чтобы проиллюстрировать это разделение, рассмотрим следующий пример разметки:
<div id="myId" class="c" user-defined-attribute="test">
В этом примере атрибутами являются «id», «class» и «user-defined-attribute». Объект JavaScript элемента div также предоставляет аналогичные свойства:
// Получение объекта JavaScript, представляющего тело
var divOb = document.getElementById(‘myId’);
divOb.id; // "myId"
divOb.className; // "c"
Эти свойства JavaScript извлекают значения, хранящиеся в списке атрибутов элемента. Например, «id» извлекает значение атрибута «id», а «className» извлекает значение атрибута «class».
В предыдущих версиях IE любые динамически добавленные свойства могли «волшебным образом» появляться в списке атрибутов элемента и, наоборот, исчезать из-за общего расположения хранилища. Это могло приводить к непредсказуемым результатам:
<div id="myId" class="c" user-defined-attribute="test">
…
var divOb = document.getElementById("myId");
// Следующий оператор неожиданно добавляет "userProperty" как
// атрибут в элемент.
divOb.userProperty = "test"// Сколько атрибутов?
alert("Total attributes = " + divOb.attributes.length);
IE9 и другие браузеры сигнализируют о трех общих атрибутах («id», «class» и «user-defined-attribute»), в то время как предыдущие версии IE сигнализируют о четырех атрибутах, добавляя в список «userProperty». Обратный пример является более распространенным – код, который ожидает появления пользовательских атрибутов в качестве динамических свойств:
<div id="myId" class="c" user-defined-attribute="test" userAttribute="test">
…
var divOb = document.getElementById("myId");
// Получение значения "userAttribute" и "user-defined-attribute"
// (работает только в IE8 и в предыдущих версиях)
var value1 = divOb.userAttribute;
var value2 = divOb["user-defined-attribute"];
Мы видели часть кода, в которой предполагается данное устаревшее поведение IE. Обеспечивающий взаимодействие способ получения неизвестных атрибутов состоит в использовании «getAttribute»
var value1 = divOb.getAttribute("userAttribute");
var value2 = divOb.getAttribute("user-defined-attribute");
В таком случае не следует запрашивать динамические свойства с помощью коллекции атрибутов.
Новые возможности ECMAScript 5
В последней группе тестов возможностей новые функциональные возможности, предоставляемые реализацией ECMAScript 5 в Chakra, применялись к модели DOM. Одна из основных целей усовершенствования модели DOM в IE9 состояла в обеспечении представления модели DOM, что вносило логический смысл в контекст семантики языка ECMAScript 5. Это было сделано гораздо проще, поскольку одной из основных целей ECMAScript 5 является улучшенная поддержка функциональных возможностей, необходимых объектам модели DOM! В нашей реализации мы представляли, что модель DOM использует максимально возможное количество собственных возможностей языка ECMAScript 5, включая широкое использование свойств метода доступа (getter/setter).
Благодаря этой интеграции платформенной функциональности все новые функциональные возможности ECMAScript5 работают одинаково хорошо как с собственными объектами, так и с объектами модели DOM.
В демонстрации усовершенствованных возможностей модели DOM показываются только 24 примера того, что становится возможным при полной интеграции модели DOM и подсистемы JavaScript с поддержкой ECMAScript 5, такой как Chakra. Мы весьма заинтересованы в этой поддержке в IE9 и планируем помочь в достижении лучшего взаимодействия для привязок языка ECMAScript в разных браузерах. Важным этапом является стандартизация этих привязок в консорциуме W3C, и мы будем рады внести свой вклад в эту работу.
Веб-стандарты консорциума W3C уже имеют предложение реализаций языковой привязки для ECMAScript как способа перевода стандартного IDL (языка определения интерфейса) в объекты JavaScript. Однако этим привязкам не хватало некоторых деталей для создания чего-то большего, чем простая привязка «базового объекта» (т.е. привязка без учета полного спектра функциональных возможностей языка ECMAScript). Поскольку другие браузеры имели гораздо более полные языковые привязки, чем просто «базовые объекты», несоответствия интеграции сохранялась. Эти несоответствия могут фактически расстроить планы разработчиков на платформе JavaScript, желающих писать абстрактные слои и функции на верхнем уровне базовой языковой поддержки. Эта необходимость соответствия привела к предложенному стандарту, названному WebIDL (язык определения веб-интерфейса). Спецификация WebIDL с гораздо большей точностью описывает порядок перевода имеющейся спецификации W3C, созданной с помощью WebIDL, в объекты JavaScript.
В следующем сообщении будет дано более подробное описание того, как мы использовали WebIDL для информационной поддержки и руководства разработкой расширенной модели DOM в IE9.
Просим вас протестировать расширенную модель DOM IE9. Ждем ваших комментариев и отзывов.
Тревис Лейтхед (Travis Leithead),
программный менеджер IE