1 (изменено: JSman, 2010-03-30 13:32:57)

Тема: 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

2

Re: WSH: Сравнение VBScript и JScript

Хочу еще добавить, что JScript чувствителен к регистру (text и Text не эквивалентны). Мне, как человеку с плохим зрением, эта особенность создает некоторое неудобство. И еще написание команд на VBScript проще - меньше разного рода скобок и не надо ";" после каждого действия (выходит, даже время экономится )

OFF: а разве не в "Script-Coding.com community" нужно такие темы? (Я тут третий день всего, может, что-нибудь не так понял)

В основе всего лежит простота.

3 (изменено: Rumata, 2010-03-30 15:33:37)

Re: WSH: Сравнение VBScript и JScript

Неплохая статья с "Солнечного ветра". В свое время Юрий Лукач проделал огромную работу, наполнив свой сайт таким большим объемом полезной информации. К сожалению она написана в 2002 году и с тех пор не изменялась. Я бы не стал сравнивать эти языки, так как у них природа разная. Об этом сказано в самом начале статьи, но не акцентировано внимание. Видимо имеет смысл начинать с того, что ECMAScript и его клоны прототипно-ориентированные языки (реализация ООП на основе прототипов), в то время как VBScript - процедурный (классы есть, но это неполная реализация ООП - есть полиморфизм, но нет наследования).

Несколько путаное описание числового типа данных - в первом чтении не очевидно есть ли в JavaScript разделение на целые и вещественные или нет.

Хотелось бы услышать от знатоков о функции LoadPicture. Так как информации по ней мало, а родной сайт тоже скуп на примеры.

Дополнение к сказанному:

В JScript такой функции нет, поэтому написать на этом языке, к примеру, отображение в браузере элемента управления ListView или TreeView становится невозможным.

Используя это решение JScript: Эмуляция функций VBScript на примере MsgBox/InputBox, теоретически можно реализовать функцию LoadPicture.

( 2 * b ) || ! ( 2 * b )

4

Re: WSH: Сравнение VBScript и JScript

Описание LoadPicture и пример. По сути дела, бесполезный объект.

Вообще, меня статья улыбнула:

1. Нельзя сравнивать два этих языка по наличию или отсутствию функций: на форуме уже есть большой опыт внедрения функций одного языка в другой, как внутри гипертекстовых приложений, так и в среде WSH.

2.

в VBScript нет механизма, позволяющего запросить количество размерностей массива

Dim Arr(1,2,3,4)

MsgBox GetArrDimensions(Arr)

Function GetArrDimensions(Arr)
     On Error Resume Next
     Dim i
     Do
          i = i + 1
          Ubound Arr,i
          if Err.Number <> 0 Then Exit Function     
          GetArrDimensions = i
     Loop
End Function

(P.S. Thanks to Xameleon)

3. Работа с SAFEARRAY не отсутствует, а представлена объектом VBArray. Аналогично касается коллекций, которые работают с Enumerator.

4.

На первый взгляд, работа с объектами ActiveX в обоих языках реализована примерно одинаково. Однако, и здесь есть тонкости. В частности, JScript не позволяет нам удалить созданный объект (см. "Удаление объектов ActiveX").

Оператор delete не предназначен для удаления переменных, только свойств объекта JScript. Сборка мусора осуществляется функцией CollectGarbage. JScript действительно имеет с этим проблему. Я думаю это можно будет рассмотреть подробнее в ближайшее время.

5

Re: WSH: Сравнение VBScript и JScript

JSman пишет:

…LoadPicture… По сути дела, бесполезный объект.

Оно годится для контейнера, например, в HTA. Я его пользую вместе с объектом «SystemTrayControl.SysTray»:

Set objSysTray = WScript.CreateObject("SystemTrayControl.SysTray", "SysTray_")

With objSysTray
    Set .Icon = LoadPicture("users.ico")
    .ToolTip = "Демонстрация использования SysTray.ocx"
    .ShowIcon
End With

6

Re: WSH: Сравнение VBScript и JScript

Предлагается к рассмотрению следующая функция получения числа измерений массива:

dim not_arr : not_arr = 1
dim arr1(2,3,5,1,7)
dim arr2()
dim arr3 : arr3 = Array(1, 2.3, "45", Array("еще", 1))
WScript.Echo "Число измерений для массивов:" & "  arr1(2,3,5,1,7)=" & ArrayDims(arr1) & _
  "  arr2()=" & ArrayDims(arr2) & "  Array(...)=" & ArrayDims(arr3) & "  не массив=" & ArrayDims(not_arr)

'Возвращает число измерений массива
function ArrayDims(arr)
  if not isArray(arr) then
    ArrayDims = -1 'Не массив - индикатор ошибки
    exit function
  end if
  dim nElCount, i, nCurElCount
  nElCount = 0
  for each i in arr 'Всего элементов в массиве
    nElCount = nElCount + 1
  next
  if nElCount = 0 then
    ArrayDims = 0 'Динамический, не определен
    exit function
  end if
  ArrayDims = 1
  nCurElCount = UBound(arr) + 1
  while nElCount > nCurElCount
    ArrayDims = ArrayDims + 1
    nCurElCount = 1
    for i = 1 to ArrayDims
      nCurElCount = nCurElCount * (UBound(arr, i) + 1)
    next
  wend
end function

Основан на положении, что массив в любом своем измерении имеет элементы 0...x, либо вовсе не имеет измерений (динамический до redim). Поправьте меня, если это не так.

Приведенный ранее вариант с ловлей ошибки требует отслеживания вручную директив "on error ..." Скажем, понадобилось игнорировать ошибки - пишем директиву вначале скрипта. Потом вдруг надо отменить игнор: комментим директиву вначале скрипта, плюс после этой функции надо еще вписывать "on error goto 0". Снова надо включить игнор - опять править в 2 местах. Правда, в этом варианте больше вычислений и текста.

7

Re: WSH: Сравнение VBScript и JScript

jite пишет:

Скажем, понадобилось игнорировать ошибки - пишем директиву вначале скрипта.

Так нельзя делать. Рассматривайте эту команду аналогично «try…catch…» — на каждый «On Error Resume Next» обязан быть свой «On Error Goto 0». Ровно в том же месте, где стоял бы «catch…».

Спасибо! Добавил в Коллекцию все три варианта: VBScript: определение количества размерностей массива.

2JSman: я правильно учёл Вашу благодарность коллеге Xameleon?

JSman пишет:

…(P.S. Thanks to Xameleon)

8

Re: WSH: Сравнение VBScript и JScript

OFFTOP: Ух давно меня сюда не заносило. А мне тут оказывается благодарности пишут. ) Клёво.

SUBJECT:   

Для чтения на стороне сервера форм, посланных запросом 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 (см. Примеры получения данных на веб-сервере).

Не согласный я. ) Ну и что что по индексу обратиться нельзя. MidB то вроде ни кто не отменял. Да и юзать SAPI.spMemoryStream для этих целей можно ) чтоб по байтам читать.

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

9

Re: WSH: Сравнение VBScript и JScript

OFF: Всегда рады Вас видеть, коллега. А насчёт благодарностей… что ж удивляться: вот, два года прошло — а я всё помню .

10

Re: WSH: Сравнение VBScript и JScript

2 alexii: Благодарствую. Кстати если в ту тему, то можно код ещё прилично ускорить (проверено), если перед перебором заранее сохранить ссылку на objFolder.SubFolders.

Set SubFolders = objFolder.SubFolders
For Each SubFolder in SubFolders
....
Next

Но это уже совсем другая история....

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

11 (изменено: JSman, 2010-11-23 01:38:46)

Re: WSH: Сравнение VBScript и JScript

alexii пишет:

я правильно учёл Вашу благодарность коллеге Xameleon?

alexii, да, спасибо :-).

Еще я очень рад, что данная тема получает развитие. Вполне очевидно, что языки сценариев имеют серьезные отличия по работе с данными да и во внутреннем строении. Однако, рассматриваемые языки вполне могут расширяться путем внедрения отсутствующих функций и объектов.  В этой связи мне представляется, что вектор дискуссии должен быть направлен на развеивание мифов об их ограниченности (таких как в статье тов. Лукача и подобных). Может быть стоит рассматривать различия языков с целью создания «костылей»?