VBScript and JScript are extremely lightweight ActiveX Scripting languages. ActiveX Scripting Engines may be used in a variety of Microsoft environments: Windows Scripting Host, HyperText Applications, HyperText Components and scripting for Internet Explorer, and classic Active Server Pages. There are other ActiveX Scripting languages, such as ActivePerl and ActivePython, but these tend to be complete languages in contrast to the minimal logic layer that VBScript and JScript provide. In fact, VBS/JS must use ActiveX/COM components to accomplish anything other than trivial tasks. This optimization results in some noteworthy shortcomings in both languages.
VBScript is typically the default scripting language for ActiveX Scripting environments, and so is used far more widely than any other scripting engine. The English-like syntax is arguably more approachable for less technical users. VBScript SafeArrays are typically the type of array expected by COM components (e.g. the ActiveDirectory Filter property).
Multiple, bidirectional, or large arguments may be passed ByRef. This bypasses creating a local copy of the
variable (increasing efficiency for large values), and allows the
function or subroutine to make changes to a variable passed to it.
FormatCurrency, FormatDateTime, FormatNumber, and FormatPercent not only make short work of tedious
formatting tasks, but also use locale-specific formatting rules.
CBool, CByte, CCur, CDate, CDbl, CInt, CLng, CSng, and CStr all
tend to overreact to unconvertable data by throwing runtime errors, but
are complemented by VarType, IsDate, IsEmpty,
IsNull, IsNumeric, and IsObject. Hex and
Oct allow converting numbers to non-decimal
strings (though no functions are provided to do the inverse). DateValue and TimeValue allow returning just the parsed date or
time values, respectively.
Along with the usual functions for individual date fields, Day, Hour, Minute, Month, MonthName, Second,
Timer, Weekday, WeekdayName, Year,
and the more generic DatePart, there are
some more granular functions for current info: Now, Date, Time. The DateSerial
and TimeSerial functions allow for complex
date arithmetic, as do DateAdd, DateDiff. Date literals are supported, using
# as the delimiter: #datestring# (using
various formats). Durations can be stored as date/time values, except
month durations.
Collections (objects containing multiple values that can only be
accessed one after the other, starting at the first) can be iterated
natively using For Each.
VBScript supports true constants, which are faster than alternatives (variables or functions), and enforce the read-only nature of constants.
With BlocksUsing With allows you to perform several
operations on an object without using a temporary variable. It is
particularly well-suited to DOM programming. The VBScript syntax for
With blocks is unambiguous, so there are no
performance or readablity drawbacks.
Withxml.appendChild(xml.createElement()"category").setAttribute("id",id).setAttribute("keywords",keywords)With.appendChild(xml.createElement()"item").setAttribute("count",count).setAttribute("tip",tip).appendChild(xml.createTextNode()text)EndWithEndWith
While standard functions like Filter,
Join, and Split are supplied; no sort, slice, splice, or
concatenation functions exist. The stack and queue functions: push, pop,
shift, and unshift are also missing.
Appending to strings in VBScript is shockingly slow. VBScript code should avoid repeated concatenation whenever possible.
Date/time values cannot be reliably converted between UTC and local timezones, since there is no way to determine either the local timezone or Daylight Saving Time (Summer Time in Europe) observance.
Automatic exception handling has two modes: on (all errors and warnings are fatal), and off. Modern, structured exception handling is not supported.
Objects are not first-class objects; assignment, for example, is
handled completely differently from built-in datatypes. Passing
functions as arguments requires using the GetRef keyword. Adding to this difficulty, naught
is expressed in many distinct (and confusing) terms: Nothing is an invalid object variable, Null adds the database-style complexity of
three-valued logic (not true, but not false either), and Empty is the value in an uninitialized variable.
Numeric values can be interpreted as booleans, as can some string values
(but only if they are numeric or boolean strings):
| Expression | Value |
True, | True |
False, | False |
Null, | Null |
Empty | False |
0, 0.0 | False |
1, 2, 3,
..., 0.1,
0.2, 0.3,
... | True |
"0", "00", "000",
... | False |
"1", "2", "3",
... | True |
"True", "TRUE", "true",
"tRuE",
... | True |
"False", "FALSE", "false", "fAlSe",
... | False |
"", "null", "yes",
"no", "t",
"f",
... | Error |
#00:00# | False |
#00:01#, #Jan 1, 2000#,
... | True |
Nothing | Error |
The only way to avoid evaluating conditions in VBScript is to put
them into separate If statements. This means
much more verbose code when the second condition relies on the success
of the previous one:
' WrongIfNotconnIsNothingAndconn.State=ADODB.adStateOpenThen' won't work' continueElse' problemEndIf' Redundant WorkaroundIfNotconnIsNothingThenIfconn.State=ADODB.adStateOpenThen' continueElse' problem (first time)EndIfElse' problem (again)EndIf' Manual Short-Circuit WorkaroundDimokok=NotconnIsNothingIfokThenok=conn.State=ADODB.adStateOpen' conditional second testIfokThen' continueElse' problemEndIf
Anyone familiar with client-side web scripting can start using JScript right away.
A reasonable complement of expected array functions is supported:
sort, split, join, slice, splice, concat, push, pop, shift, unshift, and
reverse. No grep/filter, search, or
membership-test function are provided.
Actually, all JScript arrays are hashes: an array with numeric keys
can have string keys added, and all keys can be iterated via the for...in loop. As Perl programmers already know, native
hash support allows arbitrarily complex data structures to be built
quite easily.
Using try...catch, errors can be handled much more readably,
maintainably, and conveniently.
Specially formatted comments can be used to hide code from the scripting engine based on platform or JScript version for last-minute optimization.
Date/time values can be converted between UTC and local timezones, even handling Daylight Saving Time (Summer Time in Europe).
JScript stops evaluating a conditional expression as soon as it knows the outcome, skipping superfluous subexpressions. Not only is this more efficient, but it enables subexpressions to assume previous subexpressions have succeeded:
if(conn&&conn.State==ADODB.adStateOpen)conn.Execute(SQL);
Any COM components that require reference parameters are completely useless to JScript.
Tool support for JScript tends to be somewhat scarcer than VBScript. Productive familiarity with the language is also less common, particularly outside of web development groups.
All languages should have some kind of formatting ability: C's (and
Perl's) printf, C++'s iomanip.h library, Python's % operator, etc. JScript has only toFixed and toExponential for specifying the number of digits a
number should include after the decimal. Doing something as simple as
grouping digits in a number is incredibly tedious. Localized formatting
is completely out of the question.
Dates and non-decimal numbers (e.g. hexadecimal strings) are not converted natively.
No native currency (fixed decimal) type is supported, so rounding errors may have a tendency to creep into many calculations. In fact, all numbers are treated as double floating point; no integer, long integer, or single float types are available.
No functions exist specifically for date/time arithmetic, and there is an inadequate granularity for parsing control. No date literal is supported.
Special values must be stored in variables, or trivial functions, neither of which are optimal.
with BlocksSince the syntax for with blocks in
JScript is ambiguous, members (indeed, all variables and functions
within the block) must be searched for and bound at runtime. Without any
distinguishing features, it is also impossible to see which items are
members of the with object when reading the
code.
with(o){a=x;// o.a=x or a=o.x or o.a=o.x or just a=x ?M(w);// o.M(w) or M(o.w) or o.M(o.w) or just M(w) ?}
The interpreter (and the reader) has no way to know which items
within the with block are members of o, so it has to wait until runtime and
painstakingly check each item.
Looping over items in a collection requires an Enumerator object.
for(vare=newEnumerator(fso.Drives);!e.atEnd();e.moveNext()){WScript.Echo(e.item().DriveLetter);}