Тема: WSH: Сравнение VBScript и JScript
Давайте обсудим то, что написано ниже, и подумаем.
Сравнение возможностей VBScript и JScript
Общая характеристика языков
Примитивные типы данных
Целые числа
Символы
Составные типы данных
Массивы
Коллекции
Прочие различия
Региональные настройки
Элементы ActiveX
Функция LoadPictureАннотация. Статья посвящена сравнению возможностей двух наиболее популярных в среде Windows сценарных языков: VBScript и JScript. Показано, что они не всегда взаимозаменяемы, и выбор наиболее приемлемого языка зависит от решаемой задачи.
Общая характеристика языковJScript и VBScript являются встроенными, а потому наиболее употребительными сценарными языками Windows. В большинстве случаев выбор языка определяется предпочтениями программиста, однако есть ситуации, в которых JScript либо вообще не применим, либо его применение связано с серьезными трудностями. Это объясняется различным происхождением названных языков.
JScript — это разработанная в Microsoft версия браузерного языка JavaScript, созданного корпорацией Netscape и стандартизованного ECMA (см. ECMA-262). Поэтому программирование на JScript ориентировано, в первую очередь, на веб-браузеры, поскольку обеспечивает определенную совместимость сценариев между различными браузерами.
Что касается VBScript, то этот язык является урезанным вариантом Microsoft Visual Basic, языка, созданного Microsoft специально для среды Windows и только в этой среде реализованного. В результате сценарии на этом языке не переносимы на другие платформы, но зато в полной мере соответствуют внутренней структуре Windows. Не удивительно, что для написания административных сценариев, работающих под управлением Windows Script Host (WSH), язык VBScript оказывается более удобным, как будет показано ниже.
Примитивные типы данных
Первое, что отличает эти языки, — разное количество примитивных типов данных. Если VBScript поддерживает все многообразие числовых типов Windows, то JScript может работать только с целыми 32-битовыми числами и плавающими числами двойной точности. Кроме того, JScript поддерживает только строки в кодировке Unicode, тогда как VBScript позволяет работать и с Unicode, и с байтовыми кодировками. Это приводит к следующим различиям.
Целые числа
Как сказано, JScript поддерживает только 32-битовые целые числа (двойные слова). Поэтому в тех случаях, когда нам необходимо передать во внешний мир байт (8 битов) или слово (16 битов), JScript неприменим. Эта проблема возникает, в частности, при записи в реестр Windows целых значений (см. примеры к статье "Удаление из реестра").
Еще одно различие между языками связано с выполнением битовых операций и сдвигов. В JScript все числа хранятся в плавающем формате и преобразуются в целые только на момент выполнения битовых операций. Если операция занесла в старший (знаковый) бит результата единицу, то этот результат рассматривается как отрицательное число в дополнительном коде и соответственно преобразуется в отрицательное плавающее число. При этом ошибок переполнения не возникает (подробнее см. "Последний бит").
VBScript битовые операции с беззнаковыми целыми числами выполняет правильно, а операций сдвига в нем просто нет: их приходится моделировать с помощью умножения и деления. Неприятная особенность состоит в том, что попытка преобразовать к целому типу число, выходящее за диапазон допустимых значений этого типа, генерирует ошибку. В результате каждая такая операция требует предварительного анализа значений преобразуемых переменных (см. статью "Объект Net").
СимволыТочно так же JScript не дает нам возможности работать с байтовыми кодировками символов. При этом он может перекодировать символы Unicode в ANSI и обратно, но только в кодировке, заданной по умолчанию. Более того, узнать эту кодировку в JScript мы не можем, тогда как VBScript имеет для этого функцию GetLocale (см. подробности в статье "ANSI и Unicode".) О доступе к региональным настройкам системы см. ниже.
Составные типы данных
Массивы
Одним из основных различий рассматриваемых языков является реализация в них массивов. Массивы VBScript точно соответствуют базовой структуре SAFEARRAY, которая используется в COM для передачи массивов, тогда как в JScript массивы — это просто один из встроенных объектов. Это означает, что все надстройки над Windows, такие, как IIS, WMI или MTS, передают в сценарную среду массивы в формате VBScript. Приведем только один пример.
Допустим, что нас интересует структурная иерархия какого-либо класса WMI. Она может быть запрошена через свойство Derivation_, которое возвращает массив строк, содержащих имена родительских классов для данного класса от отца к корню. Запрос иерархии класса Win32_LogicalDisk на VBScript выглядит так:
Set cls = GetObject("winmgmts://./root/cimv2:win32_logicaldisk")
deriv = cls.Derivation_ ' это массив
For i = LBound(deriv) to UBound(deriv)
WScript.Echo deriv(i)
NextТот же самый запрос на JScript приходится писать с использованием объекта VBArray:
var cls = GetObject("winmgmts://./root/cimv2:win32_logicaldisk");
var deriv = new VBArray(cls.Derivation_).toArray();
for (var i = 0; i < deriv.length; i++)
WScript.Echo(deriv[i]);Приведенный пример показывает, как передавать массивы VBScript в JScript. К сожалению, в JScript такие массивы доступны только для чтения; мы не можем модифировать массив VBScript в среде JScript. Есть и приятная неожиданность: в VBScript нет механизма, позволяющего запросить количество размерностей массива, зато объект VBArray в JScript имеет метод dimensions(), который его возвращает. (Подробнее о передаче массивов между VBScript и JScript см. "Типы данных Automation и сценарные языки".)
Массивы в VBScript имеют определенные ограничения. Во-первых, в VBScript отсутствует возможность сортировки массивов (о способах решения этой проблемы см. "Сортировка массивов в VBScript".) Во-вторых, все примитивные типы VBScript представлены как Variant, и, соответственно, все массивы представляются в нем как SAFEARRAY элементов типа Variant. В результате VBScript может принимать массивы с элементами других типов, но не позволяет "добраться" до этих элементов. Рассмотрим такой пример.
Для чтения на стороне сервера форм, посланных запросом POST, в ASP предусмотрен метод Request.BinaryRead, который принимает от клиента данные формы как SAFEARRAY беззнаковых байтов. Такая реализация явно связана с тем, что объем данных в запросе POST может быть очень велик, и нет смысла раздувать его, преобразуя каждый байт в Variant. Но в результате мы лишились возможности обработать принятые данные не только на JScript, но и на VBScript:
Dim dataLen, data dataLen = Request.TotalBytes data = Request.BinaryRead(dataLen)
В результате выполнения приведенных строк переменная data будет содержать принятый массив. VBScript сообщит нам, что это массив (isArray(data) = True) и правильно вернет его количество элементов функцией UBound(data). Однако попытка извлечь из него отдельный байт конструкцией data(i) вызовет ошибку исполняющей системы. Это одна из причин, по которым наши примеры загрузки клиентских файлов на сервер были в итоге написаны на PerlScript (см. Примеры получения данных на веб-сервере).
Коллекции
Та же проблема возникает и при чтении системных коллекций. В VBScript они перечисляются обычным оператором For Each … Next, а JScript требует использования специального объекта Enumerator (см. WDH: объект Enumerator). Например, перечисление дисков компьютера на VBScript выглядит так:
Set fso = CreateObject("Scripting.FileSystemObject") Set dc = fso.Drives For Each d in dc WScript.Echo d.DriveLetter Next
На JScript этот сценарий будет иметь следующий вид:
var fso = new ActiveXObject("Scripting.FileSystemObject"); var e = new Enumerator(fso.Drives); for (e.moveFirst(); !e.atEnd(); e.moveNext()) WScript.Echo(e.item().DriveLetter);
Прочие различия
Региональные настройки
Оба языка позволяют форматировать данные с учетом региональных настроек (locales) формата отображения чисел, дат и т. п. Названия соответствующих функций приведены в таблице:
Тип данных JScript VBScript Числа Number.toLocaleString FormatNumber Денежные единицы — FormatCurrency Дата и время Date.toLocaleString FormatDateTime
Перечислим вкратце различия между языками в работе с региональными настройками (дальнейшие примеры работы с региональными настройками см. в статье "Байт, байта, байтов").
Основное различие состоит в том, что JScript всегда форматирует результаты в соответствии с системной региональной настройкой. Ни запросить, ни изменить ее мы не можем. С другой стороны, VBScript содержит функции GetLocale и SetLocale, которые соответственно позволяют нам считать идентификатор текущей настройки и задать новую текущую настройку.
JScript, в отличие от VBScript, не поддерживает типа денежных единиц, поэтому они всегда форматируются как числа.
JScript не позволяет нам уточнить формат результата, поскольку метод toLocaleString не имеет параметров. Функции VBScript позволяют изменить многие параметры текущей настройки, хотя и не все. Например, функция FormatNumber предусматривает изменение четырех параметров форматирования чисел из семи возможных (нельзя изменить разделитель целой и дробной части числа, разделитель групп разрядов и признак отрицательного числа, т. е. те параметры, которые согласно POSIX.2 (ISO/IEC9945-2) относятся к стандарту представления чисел, см. "Кто занимается стандартизацией locale?" и стандартный файл настроек для России).
Если наш сценарий работает достаточно долго (например, реализован как сервис), то может оказаться, что пользователь в процессе работы сценария изменил какой-то параметр настройки. Функции JScript немедленно начнут использовать новое значение параметра, а VBScript требует обновления считанных им настроек. Проще всего это сделать оператором SetLocale(GetLocale) перед форматированием операнда.
Наряду с методами toLocaleString JScript поддерживает методы toString, которые игнорируют региональную настройку и форматируют соответствующие объекты по американским стандартам. Аналогичная функция CStr в VBScript частично использует американский стандарт, а частично региональную настройку. Пусть, например, наша региональная настройка указывает, что разделитель целой и дробной части числа — это запятая, а переменная x содержит число 12345.6789; тогда оно будет отформатировано так:x.toString() = 12345.6789
CStr(x) = 12345,6789
Элементы ActiveXНа первый взгляд, работа с объектами ActiveX в обоих языках реализована примерно одинаково. Однако, и здесь есть тонкости. В частности, JScript не позволяет нам удалить созданный объект (см. "Удаление объектов ActiveX").
Функция LoadPictureЯзык VBScript содержит полезную функцию LoadPicture(filename), которая позволяет загружать с локального диска графический файл для передачи элементам управления ActiveX. В JScript такой функции нет, поэтому написать на этом языке, к примеру, отображение в браузере элемента управления ListView или TreeView становится невозможным.
Юрий Лукач
Макс БаклановскийВ эту статью часто вносятся дополнения.
© 2002 Suncloud.Ru