JScript tutorial - part 1

waisttherapeuticSoftware and s/w Development

Nov 4, 2013 (3 years and 8 months ago)

145 views





JScript tutorial

by

Dino Esposito

JScript tutorial
-

part 1

Dino Esposito

covers the hist
ory and background behind Microsoft's version of
JavaScript in the first part of his on
-
line tutorial.


JScript is Microsoft's version of the ECMA 262 standard with some proprietary extensions,
mostly aimed at adding COM support. Unlike VBScript, which has

its origins in Visual Basic,
JScript isn't based on any other language and cannot be considered a stripped
-
down version of
anything. However, JScript does closely resemble the syntax of C/C++ and Java.



JScript is Microsoft's response to JavaScript, w
hich Netscape introduced with version 2.0
of its Netscape Navigator browser. This allowed Web developers to start writing more
responsive and interactive Web pages by embedding JavaScript code.



The JavaScript name is somewhat misleading as it has litt
le to do with Java, even though
the syntax is quite similar. The most significant differences, though, are conceptual rather
than technical. Java is a real programming language with a compiler and a virtual machine.
JavaScript, in contrast, is an interpret
ed language with a relatively poor arsenal of objects and
tools. As a consequence, Java programs tend to be self
-
contained, while JavaScript scripts are
limited to putting together existing objects of some hierarchy
-

for example, the browser's
object mode
l. Perhaps due to this misleading similarity, though, JavaScript has gained a wide
acceptance among the Web community.



Microsoft responded by providing Internet Explorer 3.0 with cutting
-
edge scripting
capabilities. IE 3.0 had an open architecture cal
led ActiveX Scripting (recently renamed to
Windows Script). By defining a COM programming interface for parsers, Microsoft made its
browser scripting language agnostic. Internet Explorer was capable of supporting any
scripting language for which there was
a parser module compatible with the ActiveX
Scripting specification. Since Microsoft was already promoting Visual Basic, choosing a cut
-
down version as the favoured scripting language was quite a natural choice. Thus, VBScript
came to life.



However, s
ince Internet Explorer had such a flexible architecture, it was also possible to
write a parser for JavaScript. In the process, Microsoft developers decided to add some extra
features to JavaScript, known as extensions. Since no standard was then foreseeab
le this didn't
appear to present any problems. Microsoft went for a brand new name for its version of the
language
-

JScript.

JScript versus JavaScript

For about two years in the mid 1990s, we witnessed a sort of bloodless war between
JavaScript and Jscrip
t and the products hosting them
-

the browsers and Web servers. As soon
as users attempted to standardise on one vendor's version, the competitor released an update
invalidating most of the effort. It was late in 1997 when Netscape, Microsoft and other
com
panies finally agreed on a vendor
-
neutral standard called ECMAScript, as defined by the
European Computer Manufacturers Association.



However, having a standard on paper is not the same as having a working and compliant
language implementation of it. F
or instance, JScript 3.0, which shipped with Internet Explorer
4.0, was declared ECMA
-
compliant while Netscape Communicator 4.0 supported JavaScript
1.2, which was only partially compatible with ECMA. The ECMA standard, in fact, was
based mainly on JavaScr
ipt 1.1.



Today there are versions of JScript and JavaScript which are certainly incompatible. In
practice, though, differences in the Document Object Model between browsers are more
significant than the differences between the scripting languages used
.

What's ECMA
-
compliant in Jscript?

Today, version 5.1 of VBScript and JScript are available from the Microsoft scripting Web
site at
http://msdn.microsoft.com/scripting
. Version 5.5 is already in beta, a
vailable from the
same Web site. Not all the features these versions provide are compatible with the latest
ECMA standard. In particular, be aware that the following language features that you may use
frequently aren't actually part of the ECMA 1.0 standar
d and successive modifications:



The 'switch' statement



Regular expressions



String functions which add Web
-
oriented features



Functions to manipulate strings



All the COM related features

All the rest of JScript can be safely used since it's actually part of
the standard. Functions like
anchor(), link() and italics() haven't been mentioned in the specification for a simple reason:
to keep the language as independent as possible from the Web, since an ECMA language may
be employed in any programming context. Th
e 'switch' statement, as well as some other string
functions such as replace() and match(), have been left out for the sake of simplicity.



The lack of COM support in the ECMA standard comes as no surprise. COM is a
Microsoft technology, despite succes
sful ports to platforms other than Windows. COM adds
unprecedented power to your scripts but can also make them less portable.



Remote scripting is a script
-
based technology to issue calls to remote ECMA objects. To
make it work with as many browsers a
s possible, Microsoft implemented the underlying
engine to comply with the ECMAScript standard. Consequently, though, you cannot serialise
recordset objects from the server to the client, because the transportation layer doesn't know
how to handle them. Re
cordsets are, in fact, COM objects!

When ECMA is Really Important

While ECMA is an important milestone, you don't have to regard Microsoft's extensions as
un
-
useable and to be avoided. You do need to be aware of what you can expect browsers,
other than IE,

to support. If you use COM extensively within an HTML page, you may
experience problems with non
-
Microsoft browsers. If you use the standard ECMA objects
you'll be safe whatever browser your clients utilise. However, it's best to think of JScript as a
lan
guage per se, not just for the Web. If you plan to use JScript within Windows you can feel
free to get the most out of it and to exploit all its features to the fullest.

ECMA Edition 3.0

JScript is a superset of ECMAScript. Indeed you can also use the keyw
ord ecmascript within
the <SCRIPT> tag and have Internet Explorer recognise it as a synonym of JScript. Sadly,
though, this doesn't automatically disable non
-
ECMA features in JScript.



Edition 3.0 of the ECMA standard is now ready for release. It shoul
d extend the
specification to cover most of the features that Microsoft and Netscape have introduced since
version 2.0 was introduced in April 98. Notably, the additions in ECMA 3.0 include the
'switch' statement, regular expressions, exception handling, p
lus some formatting functions.
Basically, the ECMA group has been working to make all the current features implemented
by Microsoft and Netscape browsers the new standard!



So will ECMA 3.0 remove, at least in the short term, any differences between th
e
browsers? According to Andrew Clinick, program manager in the Microsoft Script
Technology group, and member of the ECMA committee: "In the short term, there will be
some minor incompatibilities with the Edition 3.0 specification and JScript 5.0, since JS
cript
was released before the standard was completed. We are working on a newer version of
JScript that will be 100 percent ECMAScript compatible, so the next release should return us
to full ECMAScript compatibility." See Andrews article "Adventures in Sc
ripting" at
http://msdn.microsoft.com/voices/scripting.asp

for more details.



Microsoft is about to ship JScript 5.5 (see
http://msdn.micr
osoft.com/scripting
) which will
be totally compliant with ECMA 3.0. Meanwhile, ECMA 4.0 is already being worked on.


JScript tutorial
-

part 2

Dino Esposito

continues his JScript tutorial on the basics of scripting.


JScript source code is very similar to that of C, so if you already know C or C++ then learning
JScript's syntax will be easy. The

same is true if you're already fluent in Java. However
contrary to popular myth, JScript/Javascript is not derived from Java; instead both languages
were conceived as simplified versions of C++, with JScript/JavaScript an attempt to combine
C++'s core lan
guage features with the ease and flexibility of scripting.

Structure of the code

A JScript source contains blocks of statements that utilise variables, constants, expressions
and objects. It's a loosely
-
typed language, so you can combine together expressio
ns of any
type using operators. The set of native JScript operators is quite rich, at least in comparison
with other scripting languages such as VBScript.



A group of statements is enclosed within {…} curly brackets, and each statement
terminates with

a semicolon (although all current JavaScript and JScript interpreters allow
you to leave the latter out). If you're used to non C
-
derived languages such as Visual Basic, a
tricky aspect of JScript is that assignments and equality tests require two differe
nt operators
-

the equal sign (=) for assignments, and double equal (==) to test for equality. Later in the
series I'll examine other important differences between JScript and VBScript, from a practical
perspective.

Variables

Scripting languages are quite
flexible when it comes to syntax rules. For example, you don't
have to declare a variable before using it. Both the following JScript code snippets (aimed at
the Windows Scripting Host) are equally valid from a syntactical point of view:

var strText;

strTe
xt = "Hello World";

WScript.Echo(strText);



In the example above, the variable strText is declared before its use. In the next one, it
isn't.

strText = "Hello World";

WScript.Echo(strText);



There is, however, one instance when it is important to

declare a variable using the var
keyword
-

when you need to limit the variable's scope to within a function. Declaring a
variable inside a function makes it local, and ensures that no other code can access its content.
Consider this listing:

strText = "He
llo";

Foo();

WScript.Echo(strText);

function Foo()

{



var strText = "";



i=0;



while (++i<3)



strText += "X";



return;

}



The variable
strText

is initialised before the call to the function Foo(). Foo() uses a
variable w
ith the same name, and the JScript parser will consider them as the same thing,
unless you explicitly isolate Foo()'s variable within the function body by declaring it via the
var keyword.



JScript's scope granularity is limited to functions, and does

not work at the statement
level. In the example above, if you omit the var keyword from Foo() then the scope of strText
is global, and the message box displays 'XX' instead of 'Hello'. However, if there is a 'var
strText' statement anywhere in the functio
n, even after the 'global' assignment, then the
variable is treated as local. Consider this example:

strText = "Goodbye";

Foo2();

WScript.Echo(strText);

function Foo2() {

i=0;

strText = "Hello";

while (++i<3)

{



var strText;



strText += "X";

}

WS
cript.Echo(strText);

}



Surprisingly, the WScript.Echo() statement inside the function Foo2() displays "HelloXX"
instead of "XX", while the


WScript.Echo() statement outside the function displays
"Goodbye". This is because the JScript parser has scann
ed the function source, found the 'var
strText' statement, and made all references to strText inside the function local. Since JScript
doesn’t support scope at the statement level this should come as no real surprise. In C/C++,
however, things are complete
ly different!

Types

Like most scripting languages, JScript is loosely
-
typed
-

in other words, JScript variables have
no declared data type, and can change type dynamically. To change a variable's type, you
simply assign it a value of different type to its
current one, like this:

var x = 2

x = "2"




You can also freely mix types in expressions, with JScript performing automatic type
conversion, like this

var x = "2" ;

var y = x * 5

WScript.Echo(y);




The value displayed in the message box will be 1
0.



JScript supports a few fairly generic data types: numbers, strings, objects, booleans, plus
the two special types null and undefined. The undefined type is automatically assigned to a
variable immediately after its creation, and before any content

is assigned to it. A null value,
in contrast, means no value at all. Strings are delineated by single or double quotation marks.
Numbers can be both integer and floating
-
point values. A particular pseudo
-
numeric value is
NaN (Not a Number) that is assigne
d to expressions that are not numbers. Such a value is
returned by two particular global functions, parseInt() and parseFloat(), which parse
expressions and try to convert them to numbers. If they're unsuccessful, they return NaN.

parseInt("Hello");


/
/ returns NaN

parseInt("12");


// returns 12



NaN is very unusual, in that it's not equal to itself. Consider this statement:

if (parseInt("Hello") == NaN) {



Even when parseInt() returns NaN, the comparison still returns false. Luckily yo
u can test
a value against NaN via the isNaN() function, like this:

if (isNaN(parseInt(stringVar))) {



In JScript everything is an object, and every function is a method of some object. The
NaN value is a property exposed by the JScript global object,

which is made available when
the scripting engine is initialized. As global functions, parseInt() and parseFloat() are methods
of the global object.



Another commonly
-
used type is date. To simplify the tasks of formatting and
manipulating dates, JScr
ipt provides a Date object type, along with some extra functions that
are useful when working with dates. The value in a Date object represents a period in
milliseconds since midnight on 1st January 1970 (with negatives allowed for earlier dates). To
creat
e a new date object, you use the
new

operator, like this:

myDate = new Date()



By default, this gives the new object a value equal to the current date and time. JScript's
new operator is used to create objects of all types; I'll be covering objects in

a future
instalment, but in the meantime, let's have a look at other, more traditional, operators.

Operators

JScript has a full range of operators, including arithmetic, logical, bitwise and assignment. It
supports the classic C unary operators for increm
ent and decrement (++ and
--
) as well as a
compact += and
-
=syntax for sum and subtraction. Particularly interesting is the trinary
operator for conditional assignments, shown here:

MyVar = (condition ? v1 : v2)



The equivalent VBScript code requires
an If
-
End If statement, which you can partially
optimise (avoiding an Else branch) by unconditionally assigning the most likely value first.

MyVar = v1

If Not condition Then



MyVar = v2

End If



When comparing values, if the types of the two value
s are different the JScript parser
attempts a type coercion to convert both values to string, number, or Boolean type. Thus this
code:

if ( 2 == "2") {



evaluates to True. A null value equals both null and undefined expressions. In general,
comparison
s are considered potentially equal if expressions are of, or could be coerced to, the
same basic type.



JScript tutorial
-

part 3

Dino Esposito

continues his tutorial with JScript arrays.


The purpose of an array is to gather multiple items of information together under the same
name. Put another way, an array is a list of values you can access
programmatically, by
specifying the array's name plus an index (or 'subscript'). Virtually all programming languages
support arrays, although some languages make it harder than others to use them. Using arrays
in JScript is relatively easy, and as a result

they are very handy objects.



If you've worked with arrays in other programming languages, you may find JScript's
array
-
handling radically different and far less disciplined. The major characteristics of JScript
arrays are as follows:



Arrays are much

like objects, and can be manipulated using object syntax.



Arrays are sparse.



Arrays can be addressed via indexes or strings.



Arrays can be scanned using enumerators.



First we'll discover how to create an array, then we'll cover the above features in

detail.

Creating Arrays

JScript provides a built
-
in Array() object type, and to create a new array you simply create a
new instance of this type, like this:

theArray = new Array()



This example creates a new array with zero elements, which you can fi
ll later.
Alternatively, you can specify the size of the array, like this:

theArray = new Array(4)



This statement creates the new array with four (empty) elements. You can also specify the
initial contents of the array at creation time, like this:

th
eArray = new Array(1, Date(), "One", "Two", "Three")



As this example shows, an array can contain heterogeneous data
-

this one begins life
containing an integer, a date and three strings. As with JScript variables, you can change the
type of an array

element simply by assigning a different value to it.



When you call new Array() with a single parameter, its value is ambiguous
-

in new
Array(4), for instance, the '4' could be the size of the array or the value of its first element. To
resolve this

the parser assumes that a single numeric parameter indicates the size of the array,
while a single non
-
numeric parameter, or multiple parameters, represent element values.

You can access an array element by specifying the array name followed by an index w
ithin []
brackets. The simplest form of array index is a numeric subscript, such as this one:

WScript.Echo(theArray[0])



JScript's array subscripts start from zero, so this example would display the first element
of the array. As well as literal value
s, indexes can be numeric expressions, like this:

theArray[baseElem + currentOffset] = "Hello World"



Index expressions must, of course, evaluate to a positive integer.



JScript doesn't support multi
-
dimensional arrays, but you can nest arrays to

get a similar
effect. Here's an example:

itaArray = new Array("uno", "due");

theArray = new Array("one", "two", itaArray);

WScript.Echo(theArray[2][0]);



The expression "theArray[2]" is, in effect, a reference to another array object, itaArray[]
(rem
ember, array elements are numbered from zero). By placing an index value immediately
after this reference ("theArray[2][0]"), you access the first element of the 'child' array, just as
if you'd said "itaArray[0]".



The index for a JScript array doesn'
t necessarily have to be a numeric subscript
-

you can
also use key values (effectively element names). However keys can only be used with
associative arrays, which require a special form of initialisation and can't be accessed via
subscripts. See below fo
r more details.

Sparseness

Unlike some programming languages, JScript allows its arrays to contain 'holes'. For example,
if an array currently has four elements (numbered 0 to 3), you can still store data in an
element with a subscript of 10. In this case,

the size of the array (as reported by its .length
property) is automatically updated to one plus the highest subscript index.

theArray = new Array("one", "two");

theArray[10] = "eleven";

WScript.Echo(theArray.length);



The code snippet above returns
a value of 11. Unassigned elements in the array (i.e.
elements 2 to 9) will occupy no space (the array is therefore 'sparse'), but you can still safely
reference them in WScript.Echo and other methods, where they'll evaluate to empty strings
with a data ty
pe of "undefined". This happens irrespective of whether the unassigned element
is above or below the last 'real' element.

Walking Through Arrays

You can walk through the elements of an array in a couple of ways. First you can use the
traditional approach,
based on a for statement driven by an index.

for(i=0; i<theArray.length; i++)



WScript.Echo(theArray[i]);



This works, but it has a drawback
-

if the array is sparse, then the enumeration includes all
the unassigned elements. To avoid the problem
, use this code:

for(i=0; i<theArray.length; i++)



if(typeof(theArray[i]) != "undefined")



WScript.Echo(theArray[i]);



The need for this extra coding is caused by the way JScript implements arrays. Unlike
some programming languages, in

which an array is a contiguous block of memory, JScript
arrays are really collections of individual data items, which are not necessarily held in
contiguous storage. So instead of being a direct offset within a memory block, a JScript array
index is effec
tively a pointer to a variable. As part of its sparse array handling scheme, JScript
will resolve pointers to elements that don't actually exist (returning an empty value and
undefined data type), forcing enumeration loops to deal with unassigned elements.



However version 5.0 of JScript introduces a more direct way of scanning the elements of
an array, eliminating the need to check for undefined types. It's based on a new for..in
statement that closely mimics the behaviour of VBScript's for each state
ment. Here's an
example:

for(elem in theArray)



WScript.Echo(elem);



This type of for loop processes only array elements that have been defined, stopping
automatically at the last real element. Each time through the loop, the variable elem contai
ns
the subscript of the current (defined) element.



The JScript code above looks very similar to the following VBScript example:

For Each elem In theArray



WScript.Echo elem

Next



However there is a significant difference. Each time through
the VBScript loop, the elem
variable contains the value of the current element, not its index. To get the same output in
JScript, you need to apply the index to the array, like this:

for(elem in theArray)



WScript.Echo(theArray[elem]);



Even if y
ou're writing for earlier versions of JScript, all is not lost, as the Enumerator
object provides the same functionality with a different syntax:

e = new Enumerator(theArray);

for(; !e.atEnd(); e.moveNext()) {



v = e.item();



WScript.Echo(v);

}




This code also works in JScript 5.0 and later. I'll cover the Enumerator object in detail in a
future article.

Associative Arrays

Associative arrays let you index elements by key value instead of numeric subscript.
Associative arrays can be created wi
th very little effort, although the syntax is quite different
from non
-
associative arrays, with no new statement. Here's an example
-

note the {} brackets:

theArray = {"one":"First element of the array", "two":"Second element"}



For each element, you
specify a key and a value, separated by a colon; in this example,
"one" is the first element's key, and "First element of the array" is the element's value. Here's
an example with a numeric value:

"one":1



To retrieve a value, you can use this notatio
n

WScript.Echo(theArray["one"]);

You can also use JScript's object notation, like this:

WScript.Echo(theArray.one);



However you can't access associatively
-
created array elements using numeric subscripts.
In the above example, you might think that the
Array["one"] could also be referenced as
theArray[0], but it can't
-

even though "one" was the first element defined, it's not accessible
as element zero of the array.



Despite that, JScript still lets you update associative arrays using both subscrip
ts and key
values, like this:

theArray["three"] = 3;

theArray[0] = "Zero";

for (v in theArray)



WScript.Echo( v + "
-

" + theArray[v]);



This is a real recipe for confusion, as JScript treats theArray[0] as a hybrid, making it
addressable as elem
ent zero when accessed via a numeric subscript, but returning it at the end
of the list when the array is enumerated via the for..in loop. In practice it's best to stick to
accessing associative array elements solely via key values.


JScript tutorial
-

part 4

Like everything else in JScript, strings are objects, complete with built
-
in properties and
methods, and extensible too.
Dino Esposito

explains.


Strings are a fundamental data type in any programming language, and JScript is no
exception. JScript treats strings as objects and gives them a handy set of built
-
in properties
and methods, as well

as allowing you to add your own. This makes strings a very powerful
data type suitable for simple text processing as well as data storage.

String Objects and Implicit Strings

In most languages a string is simply a variable containing a sequence of charact
ers, but in
JScript strings are much more powerful. Even string constants (sequences of characters in
quotes) are treated as objects, with methods and properties. For example, you can find the
length of a given string like this:

var strText = "This is my s
tring"

WScript.Echo(strText.length)

WScript.Echo("This is my string".length)

The standard property .
length

returns the number of characters that form the string, and is
provided for string literals as well as variables.



As well as creating string var
iables and literals (also known as 'implicit strings'), you can
define string objects using JScript's
new

operator, like this:

var strText2;

strText2 = new String("This is a string object");

WScript.Echo(strText2)

Wait though
-

if string variables and lite
rals are objects anyway, why bother with this type of
formal object creation? The answer is that the JScript runtime engine treats variables/literals
and formally
-
defined objects differently when it comes to adding custom methods and
properties.



Stri
ng literals (which, perhaps surprisingly, include string variables
-

see below) are
implemented as instances of a single global String object. You can't add custom properties
and methods directly to an individual string literal, so this code won't work:

v
ar strText1 = "This is my text";

strText1.extraProp = "And this is a custom property" WScript.Echo(strText1.extraProp)


Although strText1 appears to be a string variable, in fact it's a pointer to the string literal
"This is my text", so the restriction on

custom properties applies.



In contrast, String objects created via the
new

operator are individual objects that can have
their own sets of methods and properties, so this code works:

var strText2;

strText2 = new String("This is my string");

strText2
.extraProp = "And this is a custom property"

strText2.NumOfWords = new Function("return this.split(' ').length;");

WScript.Echo(strText2.extraProp)

WScript.Echo(strText2.NumOfWords() + " words");


The custom property and method added to strText2 apply onl
y to that object, so if you tried to
call the NumOfWords() method on another object, you'd get an error.



Although you can't customise individual string literals, you can customise the string literal
object's prototype. The properties and methods you
add to the prototype are then inherited by
all new string literals (which, of course, includes string "variables"). They're also inherited by
String objects created via the
new
operator. Here's an example:

function GetNumOfWords() {



return this.split("

").length;

}

String.prototype.NumOfWords = GetNumOfWords;

String.prototype.extraProp = "Default extraProp value"

var stringVar = "Hello World"

WScript.Echo(stringVar.NumOfWords() + " words");

WScript.Echo(stringVar.extraProp)

stringObj = new String(
"This is my text")

WScript.Echo(stringObj.NumOfWords() + " words");

stringObj.extraProp = "New value for this custom property"
WScript.Echo(stringObj.extraProp)


Both stringVar and stringObj inherit the NumOfWords() method and the extraProp property.
The
re is, however, one restriction
-

variables (such as stringVar) inherit custom properties in
read
-
only form (so saying stringVar.extraProp = "New text" has no effect), whereas String
objects inherit custom properties in full read
-
write form, as shown in th
e code example.

String Methods

Besides .
prototype
, the String object has just one more property: .
length
. As the name
suggests, it returns the length in characters of the string.



Strings do, however, have a long list of standard methods, as you can s
ee from this table:

Method

Description


(Note
-

click on the examples to see the
values returned

by the methods)

anchor(anchorstring)

Returns the string wrapped in an HTML
<ANCHOR> element.

The value of
anchorstring

is used as the NAME= attribute.


Exa
mple:
myString.anchor("sect1")


big()

Returns the string wrapped in an HTML
<BIG> element.



Example:

myString.big()


blink()



Returns the string wrapped in an HTML
<BLINK> element.


Example:
myString.blink()

bold()



Returns the string wrapped in
an HTML <B>
element.


Example:
myString.bold()

charAt(index)



Returns the character at the specified position
in the string (indexed from 0).


Example:

"abcdef".charAt(2)

charCodeAt(index)



Returns the character code at the specified
position in the string (indexed from 0).


Example:
"abcdef".charCodeAt(2)

concat(otherstring)

Returns the string with
otherstring

appended
to the end of it.


Example:
myString.co
ncat(" with suffix")

fixed()

Returns the string wrapped in an HTML
<TT> element.


Example:
myString.fixed()

fontcolor(colorval)

Returns the string wrapped in an HTML
<FONT COLOR=…> element. The specifie

瑥t琠t猠s獳sg湥搠瑯⁴桥⁃li佒⁡瑴物扵瑥K
=
=
䕸a浰me㨠
myp瑲楮g⹦潮瑣潬潲o≲?d?F
=
景湴獩fe⡩湴EizeF
=
oe瑵牮猠瑨攠獴物湧⁷牡灰e搠楮⁡渠d呍i=
<FONT SIZE=…> element. The specified
楮iege爠
楮ip楺e
=
楳i
a獳sg湥搠瑯⁴桥⁓fw䔠
a瑴物扵瑥K
=
=
䕸a浰me㨠
myp瑲楮g⹦潮瑳楺eE
J

=
fromCharCode(code1,
code2, code
n
)

Returns a string given a sequence of Unicode
values. Note that this method should be
called from the
reserved String object, not
from an individual string variable.


Example:
String.fromCharCode(68, 105, 110,
111)

indexOf(substring,
[startindex])

Returns the position of the fi
rst occurrence of
a
substring
, optionally starting from (zero
-
based)
startindex
.


Example:
"the cat sat on the
mat".indexOf("cat")

italics()

Returns the string wra
pped in an HTML <I>
element.

Example:
myString.italics()

lastIndexOf(substring,
[startindex])

Returns the position where the last
occurrence of
substring

begins. Searching is
performed right
-
to
-
left, op
tionally starting
from
startindex
.


Example:



"the cat sat on the mat".lastIndexOf("the")

link(URLstring)

Returns the string wrapped in an HTML <A
HREF=…> ele
ment. The specified
URLstring

value is assigned to the HREF
attribute.


Example:



"DNJ
Online".link("http://www.dnjonline.com")

match(regExp)

Returns the first subs
tring that matches the
specified regular expression
regExp
.



Example:
"Two Ton Tan".match("T.n")

replace(regExp,
replaceText)

Returns a string where the first substring that
matches

the specified regular expression
regExp

have been replaced with
replaceText
.


Example:

"Two Ton Tan
Ton".replace("Ton", "ABC")

search(regExp)

Returns the pos
ition of the first substring that
matches the specified regular expression
regExp
.

Example:
"Two Ton Tan".search("T.n")

slice(start, [end])

Returns a substring from a start position

to
the end of the string, or optionally a specified
end position. The start position is zero
-
based,
but the end position in 1
-
based. The end
position can also be a negative number, in
which case it's taken to be an offset
backwards from the end of the str
ing.

Example:
"0123456789".slice(3,5)

small()

Returns the string wrapped in an HTML
<SMALL> element.

Example:
myString.small()

split(delimsubs
tring)

Returns an array containing all the substrings
between all the occurrences of the specified
delimsubstring
. The example below returns
an array containing the individual words in a
text string.

Example:
myString.split(" ")

strike()

Returns the string wrapped in an HTML
<STRIKE> element.

Example:
myString.strike()

sub()

Returns the string wrapped in an HTML
<SUB> element.

Example:
myString.sub()

substr(start, [length])

Returns a substring from a zero
-
based start
position,
length

characters long. If no
length

is specified, the substring continues to the
end of the string.

Example:
"0123456789".substr(3,2)

substring(start, end)

Returns a substring from the (zero
-
based)
start position to the (1
-
based) end position.
However these can be specified in either
order, so
substring(1,4)

has

the same effect as
substring(4,1)
.

Examples:

"01234567890".substring(1,4)

"01234567890".substring(4,1)

sup()

Returns the

string wrapped in an HTML
<SUP> element.

Example:
myString.sup()

toLowerCase()

Returns the string converted to lower case

Example:
"DNJ OnL
ine".toLowerCase()

toUpperCase()

Returns the string converted to upper case

Example:
"DNJ OnLine".toUpperCase()

Many of the methods reflect the browser
-
based origins of JScript, and are
designed for use
with JScript's document.write() method, which 'pumps' HTML code into the browser's input
stream. For example, you could


say:


document.write(textVar.bold())


Instead of



document.write("<b>"+textVar+"</b>")


Note that these HTML
-
oriented

methods return a value, without updating the original string.
The original version of Microsoft's Internet Client SDK incorrectly stated that, for example,
calling a string object's bold() method updated the string object itself. This has been corrected
i
n the current Web Workshop section at
msdn.microsoft.com
.



HTML
-
oriented methods are, of course, irrelevant when writing for Windows Script Host.
It's also worth noting that not all of these methods are part o
f the current ECMA standard, so
you can't be sure to find them supported in browsers other than Internet Explorer.



Two methods
-

slice() and substring()
-

appear similar, and in fact do mostly the same
thing. Despite what the MSDN documentation state
s, the second argument is optional for both
methods, and means the end of the string:

strText.substring(start[, end])

strText.slice(start[, end]

The methods behave differently in two circumstances: when you specify negative numbers,
and when the ending pos
ition is less than the starting one. If the second parameter is a
negative number, then slice() considers it to be an offset from the right end of the string.
Furthermore, the index is 1
-
based. Instead, substring() always extracts the string from the
small
er to the greater index no matter they are specified as the starting or the ending position
in the call. For example:

var text = "Dino";

alert(text.substring(2,1));

alert(text.slice(2,1));

The first message box returns 'i' namely one character from position 2. The second message
box returns an empty string because the ending position is less than the starting on
e. (Click on
the alert() statements above to see the results).


JScript tutorial
-

part 5

JScript may not be fully object
-
oriented, but it is heavily object
-
based, and lets
you
design your own object 'classes'.

Dino Esposito

shows how it's done.


"Object" is one of the most used (and abused) words in the software world today. The
meanings ascribe
d to it are many and various, but at heart an object is a collection of
properties and methods.




Although JScript can't claim to be a fully object
-
oriented language, it is, nevertheless,
heavily object
-
based. In fact everything in JScript is an objec
t: functions, strings, numbers,
arrays, you name it. As well as providing these intrinsic object types, the language makes it
easy for you to build your own, either from scratch or based on existing types.



The root of it all

JScript's objects are extreme
ly dynamic, in that you can add properties and methods to them at
any time. Although JScript doesn't support formal object class definitions, it does provide a
mechanism which uses dynamic object modification to let you effectively create your own
classes.

The same mechanism is used to create intrinsic object types.



The starting point for this system is JScript's built
-
in root object (called 'Object'), which
acts as the basis for all other JScript objects. Object has two methods; toString(), which
ret
urns a textual representation of the object, and valueOf(), which returns the object's
primitive value. It also has two properties, prototype and constructor, which are used in the
generation of new instances of Object (see below).



JScript's 'new' op
erator creates an instance of Object complete with its four
properties/methods. However it also requires you to supply the name of a 'constructor
function', which can add extra properties and methods to the new object.




JScript has a set of built
-
in
constructor functions for creating its intrinsic object types. The
simplest of these is called 'Object()' which doesn't, in fact, add anything to the basic Object
definition. It creates an empty object to which you can add your own properties and methods.
Here's an example of its use:


myObj = new Object("This is my object")


myObj is the pointer to the new object, which you can use in statements like these:


WScript.Echo(myObj.toString()) // Displays "This is my object"

myObj.newProperty = "Hello World" //

Add a custom property to this instance


JScript's other built
-
in constructor functions are more comprehensive. For example, the
String() constructor adds the properties and methods covered in part four of this tutorial, so
creating this object:


myStringO
bj = new String("This is my string")


lets you execute statements like this:


WScript.Echo(myStringObj.toUpperCase()) // Returns "THIS IS MY STRING"


JScript's intrinsic object constructors include Array, Boolean, Date, Function, Global, Math,
Number, Obje
ct, RegExp and String. See
MSDN's JScript documentation

for a full list of the
properties and methods exposed by the objects they create.


Do it your
self

As well as using JScript's intrinsic constructors, you can write your own, allowing you to
create your own object 'classes'. Here's a simple example:


function widget(name, cost) {

this.name = name

this.unitCost = cost

this.calcTotalCost = calcTot

}


function calcTot(units) {

return units * this.unitCost }


The constructor function widget() adds two properties and one method to the new instance of
Object. Initial values for the properties can be supplied as parameters to the function (see
below). The o
bject's method, calcTotalCost() is created by pointing to a second function,
calcTot(), which will be executed whenever a call is made to the calcTotalCost() method of a
widget object.




Both functions (constructor and custom method) use the 'this' id
entifier to refer to the
object on whose behalf they're currently executing. You use the widget constructor function
with JScript's 'new' operator, just like an intrinsic type:


widget1 = new widget("Left
-
hand 3mm", 0.19)


Now you can reference the object'
s properties and execute its calcTotalCost() method, like
this:


WScript.Echo("3 "+ widget1.name+" widgets @ "+ widget1.unitCost+" each equals "+
widget1.calcTotalCost(3))


Here's the result:




You can, of course, create as many new widget objects as you like (widget2 = new
widget("Right
-
hand 15mm", 0.25), etc). You can also add properties and methods to
individual instances of the 'widget' object, like t
his:


widget1.newProp = "Extra property for widget1 only"

widget1.newMethod() = newMethod // Gives just this instance an extra method by pointing to
the function newMethod()


As well as adding to individual instances, you can modify the template used to ge
nerate an
object type (intrinsic or user
-
defined), so that all objects of that type acquire extra properties
and methods. To do that, you use the type's prototype property (see below).


The constructor and prototype properties

An object's constructor prope
rty points to the constructor code that was used to build it. The
value returned for intrinsic objects isn't actually much use
-

here's an example:



str = new String("Hello World")

WScript.Echo(str.constructor);


Produces:




The constructor property of a user
-
defined object is, however, more forthcoming:


WScript.Echo(widget1.constructor)








Note that constructor is examined as a property of an individual instance (widget1), not an
object 'class', such as widget().


Useful Prototype

The prototype property is more useful, as it lets you add new proper
ties and methods to all
instances of a particular object type. Here's an example:


widget.prototype.orderType = "Online"

widget.prototype.showProps = showProps


function showProps () {

Wscript.Echo(this.name + " widget, unit cost "+this.unitCost)

}



Note
that prototype is referenced as a property of a constructor function, not an individual
object. Following these statements, all objects built by the constructor function widget() will
have a property orderType with an initial value of "Online", and a metho
d showProps().
Perhaps surprisingly, the extra items will be retrospectively added to widget objects which
were created before the prototype was updated.



You can also use prototype to add properties and methods to JScript's intrinsic object
types, so

saying:


String.prototype.NumOfWords = GetNumOfWords;


will add a method NumOfWords() (linked to a user
-
written JScript function
GetNumOfWords()) to every string object. You can even substitute your own methods for the
intrinsic objects' standard ones. He
re's an example:


function userToUpperCase() {



return "I'm a rather poor substitute for toUpperCase()"

}


String.prototype.toUpperCase = userToUpperCase;


Now this code:


str = "Hello World"

WScript.Echo(str.toUpperCase())


will return "I'm a rather poor

substitute for toUpperCase()" instead of "HELLO WORLD".
You can't change the code for a method created in a user
-
defined constructor function.



Objects within objects

An object constructor function can use the 'new' operator to create objects within obje
cts. For
example, consider the object defined below, which exposes a fully
-
functional date object as
one of its properties, plus another property called Format, which gives a dd/mm/yyyy
representation of the date. The new object type is called Today:


func
tion Today()

{

d = new Date();

this.CurrentDate = d;

this.Format = d.getDate() + "/" + (1+d.getMonth()) + "/" + d.getYear();

return this;

}


The CurrentDate property is simply an intrinsic Date() object, while the Format property
contains a string built fr
om a mixture of literal text and the values returned by the Date()
object's built
-
in methods. You can reference the Format property like this:


t = new Today();

WScript.Echo(t.Format);


You can also access the Today object's embedded Date object, and all i
ts properties/methods,
like this:



WScript.Echo(t.CurrentDate.getYear());


A small Inheritance

As well as allowing you to embed objects inside each other, JScript also supports a limited
form of inheritance. The alternative version of the Today() construc
tor shown below returns a
Date() object with an extra Format property. The code is even simpler than before:


function Today()

{

d = new Date();

d.Format = d.getDate() + "/" + (1+d.getMonth()) + "/" + d.getYear();

return d;

}


Note the use of the 'return'
statement, which makes the Date() object itself (augmented by its
new Format property) the result of the constructor. There's no use of the 'this' identifier,
because the function's working with a named object (d) before returning it. You can
manipulate th
is object just like any other Date():


t = new Today();

WScript.Echo(t.Format);

WScript.Echo(t.getYear());


As well as intrinsic objects, you can use user
-
defined objects in both embedding and
inheritance.


Anonymous Functions

When you're creating a method

in a constructor function, you don't have to put the code in a
separate JScript function. Instead, you can include it in the constructor itself by creating an
embedded, anonymous Function object. Here's an alternative version of the widget
constructor:


f
unction widget(name, cost) {

this.name = name

this.unitCost = cost

this.calcTotalCost = new Function("units", "return units * this.unitCost")

}


The first parameter to the Function constructor lists the new function's parameters, and the
second contains it
s code. A multi
-
parameter, multi
-
statement function would be defined like
this:


this.newmethod = new Function("a, b", "x=a+b; return x;")


newmethod() can be used to sum any two numbers or strings or dates
-

not the ideal demo,
admittedly, but hopefully y
ou've got the point!



JScript tutorial
-

Part 6

JScript objects not only make your applications easier to write and maintain, but
provide a great way of packaging data for
transfer between clients and servers.
Dino
Esposito

shows how it's done.

As explained in part 5 of this series, JScript objects are extremely flexible, lending themselves
to u
se as feature
-
rich arrays or COM
-
like objects. Objects have been a basic feature of the
JavaScript language since its first implementation in Netscape Navigator 2.0. They're also part
of ECMAScript, the industry
-
wide standard for JavaScript
-
like languages.



Virtually all browsers in use today support either JavaScript or JScript, the latter being
Microsoft's implementation of the ECMAScript standard. This makes JScript objects a great
tool for exchanging information and designing code in a way that all

browsers can
understand.




In this article, I'll show you how to create an object that stores data in a structure, then
exchanges it with a server using the HTTP protocol. In doing so, I'll take advantage of
Remote Scripting, a cross
-
browser compatib
le Microsoft library available for download from
msdn.microsoft.com/scripting
. I won't cover Remote Scripting in detail here, but to find out
more about it, go to
msdn.microsoft.com/msdnmag
, select MIND magazine back issues, and
search for the Cutting Edge columns in the January 2000 and April 1998 issues.


The Example Scenario

The scenario for my example is a fairly typical one: a client
-
side page where
the user enters
some keywords in order to retrieve more information from the server. In this instance the
objective is to enter an employee's personnel code in order to see her employment details.




A possible implementation for this would use a <FORM
> to capture the keywords, and an
ASP page to show the response. However JScript objects and Remote Scripting can make the
system even more interactive, by displaying the response data without leaving the current
page.




When the user submits the requ
est, the Remote Scripting runtime intercepts it and starts a
background conversation with the remote URL. The remote URL must be an ASP page which
exposes public functions; the client page invokes these functions, and receives the data they
return. This da
ta can take the form of strings, numbers and arrays, but a much better way to
pack and manipulate structured information is via JScript objects.


The Employee Object

First, let's look at a basic way to get data from a server into a pre
-
loaded client
-
side p
age,
which doesn't involve Remote Scripting. An employee object is created in the page, with data
fields (properties) such as first name, last name, title and hire date. The object is built by the
following constructor function (see
part 5
of this series for details of JScript object constructor
functions):


function Employee(empID)

{



cmd = "select firstname,lastname,title,hiredate from employees";



cmd = cmd + " where employeeid="

+ empID;




rs = new ActiveXObject("ADODB.Recordset");



rs.open (cmd, "NW");




this.FirstName = rs("firstname").value;



this.LastName = rs("lastname").value;



this.Title = rs("title").value;




d = new Date(rs("hiredate"));



s = "";



s += (d.getMont
h() + 1) + "
-
";



s += d.getDate() + "
-
";



s += d.getYear();



this.HireDate = s;





rs.close();



return this;

}


The function takes a single parameter, representing an Employee ID. The JScript code in the
function body is executed when the function is
called (via JScript's new operator
-

see below)
to create a new instance of this object type. It builds an SQL query string, establishes an ADO
database connection, performs the query and uses the results to create custom properties
("FirstName", "HireDate
" and so on) for this object.



To use the object in the client page, you write code like this:


empID = 1;

e = new Employee(empID);

alert(e.FirstName + " " + e.LastName);


This system works well, but because it uses ADO to access the database, it only

works in a
COM
-
aware browser, which rules out Netscape, Opera and most other non
-
Microsoft
products. This is a shame, as the data that's returned is usable by any Javascript
-
aware client.




A more browser
-
neutral alternative would be to create the Em
ployee entity on the server
and send it to the client as a pre
-
formed Javascript object. That's where Remote Scripting (RS)
comes in.



Bridge Over Troubled Web

Remote scripting uses a client
-
side Java applet to allow client
-
side JavaScript/JScript code to

call executable functions in ASP pages running on the server. Because the connecting
mechanism is Java, rather than COM
-
based, it runs in almost all browsers. This allows you to
keep COM
-
based functionality on the server side of the fence, and thus suppor
t a wider range
of client platforms.



An HTML page that uses RS functionality must import the rs.htm file, via this code in its
<head> section:


<script language="JavaScript" src="http://expoware/_ScriptLibrary/rs.htm">

</script>


When the page loads,

it must call the following RS initialisation function:


<script language="JavaScript">

RSEnableRemoteScripting("http://expoware/_ScriptLibrary");

</script>


The application can now invoke remote ASP functions through the RSExecute API (the
source code for

this function is in rs.htm.).




RS enables you to call a script function from the body of a remote ASP page. For example
this code:


url = "http://expoware/employee.asp";

co = RSExecute(url, "GetEmpData", empName);


calls the GetEmpData function from

the body of employee.asp, passing the value of the
empName variable as a parameter.



The ASP page must be written like this:


<%@ LANGUAGE=VBSCRIPT %>

<% RSDispatch %>


<!
--
#INCLUDE VIRTUAL="_ScriptLibrary/RS.ASP"
--
>

<SCRIPT RUNAT=SERVER Language="ja
vascript">


function MyServer() {




this.GetEmpData = DoGetEmpData;

}

public_description = new MyServer();


function DoGetEmpData(empID) {



emp = new Employee(empID);



return emp;

}

</SCRIPT>


The public_description object is the Remote Scripting v
-
tabl
e, which defines the functions in
this page that can be called remotely. In this example, the only remotely
-
callable function is
GetDataEmp(), which is internally implemented through the DoGetDataEmp() function.




DoGetDataEmp() creates and returns an

instance of the Employee object. The Employee()
constructor function, with its COM
-
based database access, now executes on the ASP
-
enabled
server, and the browser receives a pure Javascript object.


Handling the results

RSExecute() returns a data structure

called a Call Object, whose .status property contains the
result of the remote operation. If .status is zero, then the call executed successfully, and the
object's .return_value property contains the value returned by the remote function.


co = RSExecute(
url, "GetEmpData", empID);

if (co.status == 0)

{



outputForm = document.forms["output"];




// emp is an instance of Employee



emp = co.return_value;




// fills the UI fields



outputForm.firstname.value = emp.FirstName;



outputForm.lastname.value = em
p.LastName;



outputForm.EmpTitle.value = emp.Title;



outputForm.hiredate.value = emp.HireDate;

}


This approach works with any version of Internet Explorer from 3.0 onwards, and also with
Netscape Navigator and Communicator. On Netscape it gives the illu
sion of having Dynamic
HTML at work.




As described above, Remote Scripting uses a Java applet for its HTTP underpinning. Due
to differences in Java virtual machines, RS is not available on Mac and Windows 3.x. It works
fine, however, on Solaris and L
inux platforms.


JScript tutorial
-

part 7

As well as its own object types, JScript provides built
-
in support for COM objects and
collections.

Dino Esposito

explains the details.

Like COM objects, JScript objects are collections of properties and methods, but despite this
similarity the two object types are not the same. While JScript objects are

based on the
ECMAScript language standard, and supported by almost all Web browsers, COM objects are
language
-
neutral but specific to Microsoft browsers and


a small number of cross
-
platform
ports. Unlike most ECMAScript
-
derived languages, JScript support
s both these object types.


Accessing COM Objects

JScript 3.0 (which shipped with Internet Explorer 4.0) introduced a new object constructor
function called ActiveXObject(), which creates instances of COM objects. This function is, of
course, a Microsoft e
xtension of the ECMAScript standard, and very few installed browsers
other than Internet Explorer support it.




You create an ActiveXObject using JScript's new operator, like this:


var newObject = new ActiveXObject(progID[, location])


The first argu
ment is the program identifier (progID) of the object to instantiate (for example
"ADODB.Recordset"). The second, optional, argument was introduced in JScript 5.0 (with IE
5.0) to support Distributed COM, and evaluates to the network server where the objec
t is to be
created. If you have a network share called "
\
\
MyServer
\
diskC", then the server name to use is
"MyServer". You can also use a DNS format or IP address to identify the server location.



Having created your COM object, you access its methods
and properties via your JScript
object variable, using standard JSCript syntax. Here's an example:

newObject.open(cmdString, "NW");

These days, JScript isn't confined to client
-

and server
-
side web pages; you can also use it on
the Windows desktop with Win
dows Scripting Host (WSH). When creating an
ActiveXObject object under WSH, use the ActiveXObject() constructor rather than WSH's
CreateObject() method
-

object instantiation is quicker that way. Conversely, in a server
-
side
ASP page script it's more effic
ient to use the server's CreateObject() method.



JScript's COM support doesn't end with general
-
purpose objects
-

you can also work with
safearrays and enumerators. Let's see how.


Safearrays

JScript arrays are just like other objects, that is collect
ions of values accessible through
properties (in this case, the properties are the array's indexes). In VBScript (and in COM in
general) arrays have a different structure, and are termed safearrays. Together with BSTR and
Variant, safearrays are one of the

main COM data types.




A safearray is a structured data type that contains an array of other data types. It's called
'safe' because it contains information about the bounds of each array dimension, and limits
access to elements within those bounds. A
rrays created in VBScript and Visual Basic are
automatically safearrays, as are arrays made available by methods of COM objects.




You can't directly access the elements of a safearray from JScript, but you can convert an
entire safearray's contents t
o a standard JScript array. First, you need to create a 'handle' to the
safearray in the form of a VBArray object type. To do this, you use JScript's built
-
in
VBArray() object constructor, like this:



mySafeArray = new VBArray(safeArray)


The function's p
arameter must be a reference to a safearray returned by a call to a VBScript
procedure or COM object method. The object which VBArray() returns isn't a JScript array,
but still a 'foreign' data type, which exposes methods such as dimensions() and ubound()
which you can use to assess the structure of the safearray. To get at the array's contents, you
can use the VBArray() object's toArray() method, like this:


safeArrayData = mySafeArray.toArray()


This method returns a standard JScript array containing a co
py of the safearray's data. If the
safearray has multiple dimensions, they're flattened (for example, a 3 by 2 safearray becomes
a six
-
element JScript array). Updates to the JScript array aren't propagated back to the original
safearray
-

in fact there's n
o way to directly update a safearray from JScript.




Here's an example of VBArray() use, from the <body> section of a web page:


<SCRIPT LANGUAGE="VBScript">

Function CreateVBArray()

Dim a(1, 1)

a(0,0) = "0, 0"

a(0,1) = "0, 1"

a(1,0) = "1, 0"

a(1,1) =

"1, 1"

CreateVBArray = a

End Function

</SCRIPT>


<SCRIPT LANGUAGE="JScript">

var a = new VBArray(CreateVBArray());


document.write("Source array has "+a.dimensions()+" dimensions.<br>")

var b = a.toArray();

for (i = 0; i < b.length; i++)


{

document.write
(b[i]+"<br>");

}

</SCRIPT>


Enumerating COM Collections

In practice you're unlikely to need VBArray() very often, and when you do it'll probably be to
handle an array returned by a COM object method rather than a VBScript function. This isn't,
however, tru
e of enumerators, an important COM feature which has plenty of everyday uses
in JScript.




VBScript has enumerators built in, with this general syntax:



For Each elem In coll



Next


Unfortunately JScript doesn't have For..Each construct. However, fr
om JScript 3.0 onwards
you can use the Enumerator object type instead. Here's an example:



rs = new ActiveXObject("ADODB.Recordset");

rs.Open("select * from employees", "DSN=NW");


e = new Enumerator(rs.Fields);

for(; !e.atEnd(); e.moveNext())

{

x = e.ite
m();

WScript.Echo(x.Name);

}


You initialise an Enumerator object by passing it a collection, in this example the Fields
collection of an ADO recordset object. Collections differ from arrays in that their members
cannot be accessed directly
-

instead of us
ing indexes, you can only move the current item
pointer to the first or next element. A COM collection that can be enumerated through the
For..Each or Enumerator interface is characterized by the _NewEnum property.



The Enumerator object makes informa
tion from the collection available through its
programming interface, which exposes four methods and no properties. The methods are
moveFirst(), moveNext(), atEnd() and item(), and their roles are quite straightforward and
self
-
explanatory.



In a VBSc
ript For..Each loop you can directly access current element of the collection. In
JScript, however, you need to instantiate it explicitly, like this:


x = e.item();


The For..In Statement

JScript 5.0 introduced a new construction
-

for..in
-

that appears s
imilar to VBScript's
For..Each. Here's an example:


var s = ""

a = new Array("Item 1", "Item 2", "Item 3")

for (key in a)

{

s += a[key] + "
\
r
\
n";

}


However, this construction can't be used with COM collections, only with JScript objects and
arrays, where
it executes one or more statements for each object property or array element. If
you try to use it with a COM collection, you won't get an error, but the enumeration won't
start. To enumerate collections in JScript you still have to use the Enumerator obje
ct.


Summary

In general, JScript and VBScript have quite similar functionality, and choosing between them
is largely a matter of personal preference. However if you need to do a lot of COM
-
based
programming then VBScript is probably the better bet.



JScript tutorial
-

part 8

For years, JScript lacked exception handling features to match those of VBScript. Since
version 5.0, however, it's been one step ahead.


Dino Esposito

explains.

Early versions of JScript lacked VBScript’s exception handling features, while VB in turn
lacked JScript’s runtime code evaluation (eval() function). Microsoft promis
ed that, from
version 5.0, the two languages would become as functionally equivalent as possible, so
VBScript 5.0 introduced code evaluation, and JScript at last offered an equivalent to
VBScript's popular On Error..Goto statement.



Not surprisingly,
each language’s brand
-
new feature was an improvement on the other’s
older one. VBScript 5.0 has a more powerful set of statements for evaluating code at runtime
than JScript's, while JScript 5.0 has a fully
-
fledged mechanism for trapping runtime errors
tha
t VBScript and Visual Basic developers can only dream of (although VB will catch up with
version 7.0 in Visual Studio.NET.)



In this article, I'll delve deep into the programming features of JScript 5.0’s exception
handling.

What's an Exception?

An ex
ception is any runtime occurrence that an application isn’t expecting, or doesn't want, to
happen. It can be the result of a programming error (such as a call to a non
-
existent function)
or a system
-
generated error such as an attempt to access files on an
empty floppy drive. In
JScript 5.0, it can also be an application
-
level occurrence such as a data validation error.



There are no general
-
purpose guidelines for handling exceptions


how you respond to
one depends on the courses of action available to

the application (Is a retry possible? Is the
error fatal?), and how sophisticated you want your application’s exception
-
handling to be. In
practice though, exception handling normally means trapping an error then degrading
gracefully, or at least more gra
cefully than with one of the system’s standard, and often
unintelligible, system message boxes.



Exception
-
handling code is not part of the application, in the sense that it does not fall into
the standard flow. Instead, it’s a fire
-
fighting resource
that attempts to resolve any situation
that has caused the standard flow to break. Instead of error
-
checking the return value after
each method or function call, you declare an exception handler routine, which the system
invokes automatically when an error

occurs. In pseudo
-
code, it looks like this:

Execute {statement
-
list} In Case Of Errors {exception
-
handler}

The exception
-
handler code will be executed only if an error occurs in the statement list.

Handled and Unhandled Exceptions

When an exception condit
ion occurs, it's because either the application (or one of its
components) or the system has raised it. For example, if you try to write to a floppy drive with
no disk in it, the system detects the problem and raises an exception.



An exception handle
r can either deal with the problem itself (‘handle’ it) or, if the
exception is one it can’t resolve, pass it on to the next level in the system’s exception
-
handling hierarchy. If an application’s exception handler successfully deals with a problem,
the ap
plication can continue to run. If the handler has to pass the exception on, the application
will typically stop with a runtime error message.



JScript 5.0 provides three new statements for exception handling:

try {}

defines a block of code that has an

exception handler defined for it.

catch {}

defines a block of code which forms the exception handler for the preceding try{}
code block.

throw

is used either by code in a try{} block to programmatically invoke its catch {}
exception handler, or by an exce
ption handler to pass the exception on to the next level of
exception
-
handling (such as the script engine or operating system).

To illustrate these statements, let’s first see how JavaScript performs without them. Here’s a
Windows Scripting Host applicatio
n (held in a .js file):

fso = new ActiveXObject("Scripting.FileSystemObject");

f = fso.CreateTextFile("a:
\
\
foo.txt");

WScript.Echo("Closing the application");

If this code is executed when there’s no floppy disk in drive A:, the system generates a
message
box like this:





The application is then terminated, and the ‘Closing the application’ message is not displayed.



Let's rewrite the code with exc
eption handling.

fso = new ActiveXObject("Scripting.FileSystemObject");

try

{



f = fso.CreateTextFile("
a:
\
\
foo.txt
");



Wscript.Echo(“This won’t be displayed when there’s no disk in A:”)

}

catch(e)

{



WScri
pt.Echo("Got an error!");

}

WScript.Echo("Closing the application");

An exception raised by any of the statements inside the try {} block will cause the catch {}
block to execute, so when the fso.CreateTextFile() method call fails, the catch block is
invok
ed. Because this block doesn’t execute a throw statement to pass the exception on, it’s
deemed to have successfully resolved the error, and the application is allowed to continue
running.



It’s important to note, however, that the application continue
s from the first statement
after the try{}..catch{} block


once an exception has occurred, the try{} block is abandoned.
So when this code is executed with no disk in drive A:, you see the ‘Got an error!’ message
first, then the ‘Closing the application’
message. The ‘This won’t be displayed..’ message
doesn’t appear, because it’s after the exception
-
generating fso.CreateTextFile() call in the
try{} block.


The Catch Block and Error object

JScript 5.0’s exception handling system takes advantage of the Win3
2 Structured Exception
Handling (SEH) mechanism. This allows it to intercept exceptions raised by system
components, as in the case of the ‘disk not ready’ message. An exception handler (catch {}
block) can also handle exceptions raised by the application
itself, via throw statements
executed within its try{} block.



A catch {} block takes a single parameter (‘e’ in our example), which supplies it with
information about the exception it’s been invoked to handle. This parameter can be any data
(string,
number and so on) or object type, including JScript 5.0’s new Error() intrinsic object.
Applications can pass any type of parameter, but system errors always pass an Error object.



An Error object has two properties, .description and .number. As their

names suggest,
these properties indicate the reason for the error and the code that identifies it. The error
number is a 32
-
bit value. The upper 16
-
bit word is the facility code, while the lower word is
the actual error code. To extract the error code you

apply the following bitmask:

errorCode = e.number & 0xFFFF;

In the message box shown above, 0x0047 (71 in decimal) is the actual error code.

The throw Statement

When used in a try{} block, the throw statement generates an exception that is handled by the
block’s catch {} exception handler. The statement is followed by a value, of any type. Here
are some examples:

try {



e1 = new Error(description, number);



throw e1;



e2 = "Internal Error";



throw e2;



throw 129;

}

catch {… etc

This use of throw allow
s applications to handle their own error conditions via exception
handlers. This is a much more elegant and effective approach than numeric error codes, and is
particularly suited for high
-
level languages such as scripting languages, Visual Basic and
Java.



The other use of throw is from within a catch {} block, where it’s used to pass the current
exception on to the next level of the SEH hierarchy. You’d want to do this if you’d written an
exception handler to deal with a specific range of errors, and

the current error wasn’t among
them. All you need to do is throw a new exception, passing on the parameter the catch {}
block received as its parameter (a process known as ‘rethrowing’). Here’s an example:

catch(e)

{



switch(e.number & 0xFFFF)



{



// handle known errors



case 71:



HandleError71();



break;



case 44:



HandleError44();



break;



// rethrow the error for next handlers



default:



throw e;

}

}

Note that you don’t have to worry about (and can’t, in fact, control) the location of the
exception handler that will receive your throw statement


that’s the job of the system. For a
JScript application, the ‘system’ isn’t Windows, but the JScript runti
me engine. If the
exception remains unhandled further down the line then the system will stop with a message
box.



Application vs System errors

The throw statement’s ability to pass data of any type is something of a double
-
edged sword,
since it means th
at the corresponding catch {} block can’t be certain what data it’s going to
receive.




If a catch {} block only has to deal with system
-
generated exceptions (there are no throw
statements in its corresponding try{} block), then it can assume that it
will always receive an
Error object with .description and .number properties. If your try {} code does throw
application
-
level exceptions, however, then the catch {} block will have to deal with them
too.



It’s OK for your code to create its own Error
() objects (and thus avoid possible data
mismatch errors), but that does introduce a risk of inadvertently duplicating system error
numbers. One technique for avoiding this is to define your own exception object type using an
object constructor function (s
ee part 5 of this series). If you use that for all your application
-
level exceptions, your catch {} blocks can check for it, and handle application and system
exceptions separately. Here’s an example:

fso = new ActiveXObject("Scripting.FileSystemObject");

try {



f = fso.CreateTextFile("
a:
\
\
foo.txt
");



// Application
-
generated exception



myErr = new appError("App
-
level error", 42)



throw myErr

}

catch(e) {



if (isAppError(e)) {



WScript.Echo("Application
-
level erro
r", e.description, "trapped")



} else {



// pass system errors on to system



throw e

} }

WScript.Echo("End of Application")

function isAppError(obj) {

var x = false

if (typeof(obj) == "object") {



if (obj.constructor == appError) {



x = true



}

}

return x }

// Constructor function


function appError (description, number) {

this.description = description

this.number = number }

And finally…

As well as try {} and catch {}, you can add a third block to an exception
-
handling
construction


finally
{}. Here’s an example:

fso = new ActiveXObject("Scripting.FileSystemObject");

try {



f = fso.CreateTextFile("
a:
\
\
foo.txt
");

}

catch {

WScript.Echo(“Error

“,e.description)

}

finally {

WScript.Echo(“An error has been han
dled, try block abandoned”)

}

Statements in the finally {} block are executed after the catch {} block has finished, but only
if the block handles the error itself


if it rethrows the error, the finally {} code isn’t executed.
MSDN’s Windows Scripting Tec
hnologies
JScript documentation

says otherwise, but that’s
how it works on our system!

Summary

JScript 5.0's exception handling mechanism, based on try/
catch/throw statements, is the best
of today's scripting languages. Compared to it, VBScript's On Error…Goto technique appears
just a bit old
-
fashioned. What's more, using try/catch/throw is good preparation for upgrading
to non
-
scripting languages like th
e newly announced C#.


JScript tutorial
-

part 9

JScript's eval() method lets you create executable code at runtime, and import it from
external sources.
Dino Esposito

explains.


Since its first release, JScript has provided an eval() method, which evaluates and executes
code at runtime. This allows you to dynamically create and manipulate code b
locks in your
applications. For example, you can store some JScript code in a string variable, then tell the
runtime engine to execute it as easily as you can search or concatenate a string.



The eval() method is quite powerful, though it does have on
e significant limitation. In this
article, I’ll describe its implementation and programming interface, comparing it to its slightly
more capable VBScript counterpart.

A global method

In JScript everything is an object or related to one, and although eval()

looks like a free
-
standing function call, it’s technically a method of the language’s root object, Global (see part
5 of this series). eval()’s job is to parse and execute a string value as if it was hard
-
coded into
the script source at the point where th
e eval() call is made. In effect, it works like an
embedded JScript parser hidden in your programs.



The method’s syntax is simple:

eval(strCode)

Where strCode is a string (literal, variable, expression, property


whatever you like)
containing valid
JScript code. As with all JScript code, multiple statements can be
concatenated using the ; symbol. For example, the following code snippet

eval("var theDate = new Date();WScript.Echo(theDate)");

declares and initialises a variable called theDate, then dis
plays it in a WSH message box. The
code string can come from just about any source, including database servers, ASP pages and
values returned by function calls.

Potential Usage

There are two main ways in which you can take advantage of eval(). First, you c
an use it to
construct and execute code which can’t, for one reason or another, be hard
-
coded into the
script source. Second, you can use it to import blocks of code from external files, and to build
variable and object definitions using data from external

sources such as an ADO recordset.



The first use often involves the dynamic construction of variable or object names. This is
sometimes a poor alternative to using objects, properties and methods, but on some occasions
eval() is the simplest and most

effective way. Here’s an Internet Explorer routine which sets
the .src properties of five similarly
-
named image objects to the same value:

function setImgSrcs(namePrefix) {

var i;

for (i=1; i<6; i++) {

eval(namePrefix+i+”.src = ’p0.gif’”)

} }

If the value

of namePrefix was “score”, then on the first iteration, eval() would execute this
statement:

score1.src = ‘p0.gif’

The next time it would be score2.src, and so on.



The second use of eval() lets you assemble an application’s code at runtime from
dyna
mically
-
selected external sources. It’s powerful stuff, but you do need to remember
eval()’s weak spot


context. Consider this WSH script file:

WScript.Echo("Code in main script file")

eval(Include("extcodefile.js"));

showMessage("Back in main script file

again")

function Include(fileName){



fso = new ActiveXObject("Scripting.FileSystemObject");



f = fso.OpenTextFile(fileName);



s = f.ReadAll();



f.Close();



return s;

}

When this script is executed, you see two message boxes (“Code in main..” and “Bac
k in
main…”). But where is the declaration of the function showMessage()? The answer lies in the
contents of the file "extcodefile.js":

function showMessage(mess) {



WScript.Echo(mess)

}

This code doesn’t do any processing (although it could do)


instead

it just declares the
function showMessage(). The eval() method call in the first script file processed its contents
as if it had been hard
-
coded into the source at that point. This made the function available to
code further down the script.



A key p
oint to note here is that eval() is used to process the string returned by Include().
To make things neater, couldn’t we have used eval() from within the Include() function?


The
answer is yes in theory, but no in practice, because of the rules of context.



The code evaluated by eval() method is placed in the context in which eval() was called.
In the example above, that’s the main code block of the first script file. As a result, the
showMessage() function is available to any inline code or procedure
executing after the eval()
call has executed.



If eval() had been executed within the function Include(), like this:

function Include(fileName) {

… // (function code)


f.Close();


eval(s);


return;

}

then showMessage() would have become a private func
tion, embedded within Include(), and
unavailable outside of its scope. When importing code via eval(), the golden rule is to imagine
that you’re hard
-
coding the source lines at that point in the file. Whatever scope would apply
to hard
-
coded source will ap
ply to the code imported by eval()


it’s as simple as that.

Using eval() to create objects

Another interesting use of eval() is creating and initialising custom objects. Suppose that you
need to create an object to hold data from an ADO recordset, with a
property corresponding to
each field in the ADO record. To create the object, you use an object constructor function (see
part 5 of this series).



Normally a constructor creates properties and gives them initial values, like this:


function myObj(Last
Name, FirstName) {

this.LastName = Lastname

this.FirstName= FirstName}


In this case, however, we only need to give the properties their names
-

they'll be assigned
values later on, as we read records from the recordset. So instead of passing data values a
s
parameters to the constructor function, we pass it the ADO recordset object's .fields
collection, which includes a .Name property for each field. Thanks to eval(), we can use the
.Name values as the names of properties in the new object, even though we d
idn't know what
those names were when we coded the constructor function. Here's the code:


function record(fieldColl) {

var i, cmd;

for (i=0; i<fieldColl.Count; i++)



cmd = "this." + fieldColl.Item(i).Name +" = null"



eval(cmd)

}


If the .Name property

of the first field had a value of 'LastName', then the first time through
the loop, the value of 'cmd' would be:


this.LastName = null

the null value is necessary in order to satisfy the syntax requirements of the property
-
creating
statement; actual value
s will be placed in the property by ADO
-
handling rountines later.


Injecting code in the program’s main body

JScript has no equivalent to VBScript’s ExecuteGlobal statement, which acts like eval() but
puts the code in the global scripting namespace regardl
ess of where it was called from.
Instead the rule is always that code generated by eval() has the same context (and therefore
scope) as the eval() method call itself.



If you need to import external JScript code into HTML and ASP documents, then a qui
ck
and easy way is to use the HTML <script src=> tag, like this:

<script language=”JScript” src=”myfile.js”></script>

This imports the contents of “myfile.js” into the document as if it was an inline script
(<script>…</script>) element, so any top
-
level fu
nctions it declares become callable by all
code in the page. You can place <script src=> elements anywhere in the document where it’s
valid to place inline scripts. The script file (“myfile.js”) does not need to contain
<script>..</script> tags.



Earl
y versions of Windows Scripting Host (WSH) don’t support HTML <script> tags, so
you can’t import code that way. Instead, you can use the eval/Scripting.FileSystemObject
method shown above. In the long term, however, it’s best to upgrade to the WSF (Windows

Script File) format supported by WSH 2.0.



WSF is an XML
-
based format that allows you to mix JScript and VBScript scripts (plus
other languages supported by installed scripting engines) in a single file, just as you can in
HTML documents. It supports

the <script> element, for inline and linked (src=) scripts.
Here’s an example from the MSDN Scripting Technologies section:

<Job id="IncludeExample">

<script language="JScript" src="FSO.JS"/>

<script language="VBScript">


' Get the free space for driv
e C.


s = GetFreeSpace("c:")


WScript.Echo s

</Script>

</Job>

For more details (including the contents of “FSO.JS”), see


http://msdn.mic
rosoft.com/scripting/default.htm?/scripting/windowshost/doc

/wsAdvantagesOfWs.htm
.

Summary

Runtime code evaluation has been a feature of JScript since version 1.0, and has helped to
make it an extremely flexible language. JScript’s eval() method is powerf
ul, but has a
significant limitation; it can’t place code outside of its own context. In early versions of WSH,
eval() was the only way to import code into a main script from external files, but WSH 2.0’s
Windows Scripting File format supports the HTML
-
der
ived <script src=> tag, making
imports easier.

JScript tutorial
-

part 10


JScript's dynamism extends to letting you add properties and methods to objects on the
fly, and write functions that can accept varying numbers of parameters in their calls.
Dino Esposito

explains.

In Part 9 of this series we looked at runtime code evaluation, a dynamic feature which JScript
inherited from third
-
generation interpreted languages. JScript
carries this dynamism into its
object
-
oriented features, by allowing you to add properties and methods to objects after
they've been created (a system called 'expando properties').


Back on traditional ground, JScript lets you treat function arguments (par
ameters) as optional,
including them in some calls and omitting them in others.


It all adds up to a very flexible
language, but one in which you need to take plenty of care!



Expando Properties

In JScript, objects are created by calling constructor funct
ions (
see part 5
for full details). The
language comes with built
-
in constructors for its intrinsic object types (String(), Date() and so
on), and you can write your own constructors

for custom types, like this:


function Player(name) {

this.name = name

this.score = 0}


player1 = new Player("Dino")


JScript also provides a way to add extra, application
-
specific properties and methods to
existing object types, via the constructor's bui
lt
-
in .prototype property. Here's an example:


Player.prototype.handicap = 0


Now every object in this document (HTML page, or .js file in Windows Scripting Host) built
by the Player() constructor will have a .handicap property with a default value of zero
.


You can also, however, add extra properties
-

called 'expando properties'
-

to individual object
instances. Doing this couldn't be simpler
-

just assign a value to the new property, like this:



player1.bonus = 10


Now the object 'player1' has a .bonus
property. Other objects of the Player() class won't have
one, although you can add .bonus properties to them on a per
-
object basis.

You can also add extra methods to an object, like this:


function doubleScore () {

this.score = this.score * 2 }


player1.do
ubleScore = doubleScore


player1.doubleScore()


In Internet Explorer 4.0 and later, expando properties (though not methods) can also be added
to objects derived from HTML tags, by adding pseudo
-
attributes to the HTML tags
themselves. Here's an example:


<i
mg src = "dino.jpg" id="player1Pic" playername = "Dino Esposito">



<script>

if (typeof(player1Pic.playername) != "undefined") {

alert("Player 1 is "+player1Pic.playername)

}

</script>


The playername= attribute of the <img> tag is automatically transforme
d into the .playername
property of the player1Pic object. The script's defensive programming ('if
(typeof(player1Pic.playername) != "undefined")') protects against situations where the HTML
tag doesn't contain a playername= attribute.


Danger!

Expando prop
erties make things quick and easy, but they can also be dangerous. It's all too
easy to create a new property instead of updating an existing one, just by misspelling the
existing property's name, as in this example:


player1 = new Player("Dino")


player1.
scre = 10


The object player1 has a .score property, created by the Player() constructor function (see
above). But the next statement misspells its name, adding a new .scre property to the object
and leaving its .score value unchanged. Because JScript is c
ase
-
sensitive, even saying
'player1.Score' would have the same effect.



There are two ways to guard against this problem. In Internet Explorer 4.0 and later you can
disable the creation of expando properties and methods altogether (at the HTML tag and
scr
ipting levels) by setting document.expando = false (tip
-

make this the first script statement
in the document, in an inline script near the start of the <head> section). Unrecognised HTML
attributes will now be ignored, and any attempt to dynamically add
properties in a script will
generate a JScript error.



The other, more general strategy is to use methods rather than directly accessing object
properties. Here's an example:


function Player(name) {

this.name = name

this.score = 0

this.getScore = new Fun
ction("return this.score")

this.setScore = new Function("newVal", "this.score = newVal")

}


player1 = new Player("Dino")


player1.setScore(player1.getScore() + 10)


Instead of directly updating player1's .score property, the final statement calls its .setS
core()
method. This is much safer, as simply misspelling a method name won't add an expando
method to an object. By reading the current score value via the object's getScore() method, the
code avoids directly accessing the .score property altogether.



Thi
s technique achieves greater encapsulation and potential for polymorphism, since outside
code doesn't even have to know what score
-
recording properties the object actually has. It
also explains why the intrinsic JScript objects have a very small number of
properties and lots
of methods.




Optional function call arguments

Sometimes you can call a COM object method without supplying all the arguments
(parameters) that the method can theoretically accept. This is because the COM object has
declared one or mor
e of its arguments (at the end of the arguments list) as optional. C++ class
methods can do the same thing. VBScript doesn't have this capability, but JScript does.


Every JScript function has a built
-
in arguments property (actually an array), which contai
ns
all the arguments passed when the function was called. The following function returns a
comma
-
separated string with all the arguments it's received:



function CallMe(p1, p2, p3)

{

var buf = "";

for (var i=0; i<arguments.length; i++)

buf += arguments[i]

+ ", ";

return buf;

}


WScript.Echo( CallMe(1,2) );

WScript.Echo( CallMe(1) );

WScript.Echo( CallMe(1, 2, 3, 4) );


The function declares three parameters. However, you can safely call the function with two
arguments or less
-

or, indeed, with more argume
nts than it has 'official' parameters. You can
even create functions which don't have any declared parameters, then pass them an arbitrary
number of arguments in any combination of data types.



The only rule is that when you call a function, the list of a
rguments must be contiguous, so
while this call is OK:


x = CallMe(1)


this one isn't:


x = CallMe(1, , 3)


The attempt to omit the p2 parameter, while supplying a value for p3, causes a JScript error.




Defensive programming

You don't have to access a fu
nction's optional parameters via its .arguments array. Instead you
can access them by their names, provided you first use JScript's typeof() method to check
whether they've been supplied or not. You can also use typeof() to check the data type of a
paramet
er's value, killing two birds with one stone.


Here's a more tightly
-
controlled version of CallMe():


function CallMe(p1, p2, p3)

{

var callError = false; errMsg = ""


if (typeof(p3) == 'undefined') {

errMsg += "At least 3 arguments must be supplied. "

ca
llError = true}


if (typeof(p2) != 'number') {

errMsg += "The second argument must be a number. "

callError = true}


if (callError) {

return "Error(s): " + errMsg}


var buf = "";

for (var i=0; i<arguments.length; i++)

buf += arguments[i] + ", ";

return buf
;

}


typeof() returns 'undefined' for a named parameter that's been omitted from a function call.
The test for a data type of 'number' on the p2 parameter, meanwhile, checks not only that a
value has been supplied, but also that it's a numeric one.

Getting

things sorted


Optional parameters are particularly useful in complex functions which use callbacks and
optional data. An example of this is the sort() method of JScript's intrinsic Array() object. The
JScript language reference

contains this prototype for it:


arrayobj.sort(sortFunction)


sortFunction is a user
-
written JScript function that the sort() method will repeatedly call
during the sorting proces
s. This function must accept two values (elements of the array being
sorted), and return a value indicating which one (if either) has a greater sort value. This allows
you to control the sorting sequence, like this:


a = new Array("B", "C", "A")


function
mySort(p1, p2){

return (p1 > p2) ? 1 : (p1 == p2) ? 0 :
-
1

}


a.sort(mySort)

WScript.Echo(a)


However if a simple ASCII sort is all you need, you don't actually have to write a sort
function. Instead you can just say something like this:


a = new Array("B"
, "C", "A")

a.sort();


and it will work just fine. Why? The sort method checks if it's received an argument of type
'function'. If it has, that's considered the callback function and invoked as explained above. If
it hasn't, the method sorts the array itse
lf in ascending ASCII character order.

JScript tutorial
-

part 11


JScript.
NET combines the traditional flexibility of scripting languages with the tighter
controls and higher performance of true compiled, object
-
based code
.
Dino Esposito

explains.

With the advent of the .NET platform new compilers are being introduced for Microsoft’s
mainstream languages such as Visual Basic and Visual C++. Jscript is getting an upgrade too
in

the form of JScript.NET, which combines the best of the legacy script world with the
industrial
-
strength features of class
-
based languages. The new features in JScript.NET have
been developed in collaboration with the ECMAScript committee, and are expecte
d to be part
of the upcoming ECMAScript 4 standard.

JScript.NET is heavily based on the .NET framework and primarily aimed at Microsoft server
environments, so don’t expect to see .NET support on the client side via Web browsers,
especially on non
-
Microsof
t platforms. JScript.NET will, however, appear as a desktop
scripting language through a new version of Windows Script Host.

New Features

JScript.NET has a dual character. It’s a true scripting language like its predecessors, but it’s
also a true object
-
or
iented language like the other .NET languages. This results in a truly
heterogeneous set of features. On the one hand are compiled code, strong typing, inheritance,
function overloading and property accessors, along with cross
-
language support and full
acc
ess to the .NET class framework. On the other are scripting language traditions such as
typeless programming, expando properties and dynamic code declaration/execution.

Strong Typing

JScript.NET supports new primitive data types, although you can still use

typeless variables
as well. Using proper types in programming is, however, advantageous, improving execution
speed and compile
-
time type checking, and allowing for more self
-
documenting and easily
maintainable code.

The new data types supported by JScript
.NET are boolean, double, float, int, long, number
and string. Number is a double and its equivalent .NET data type is System.Double.

In most
respects Jscript’s syntax is very similar to C/C++, but the syntax for declaring and initialising
JScript.NET type
d variables is slightly unusual. For example, to declare an integer you would
write code like this

var iValue1 : int;

var iValue2 : int = 3;

The new syntax is designed for compatibility with existing JScript code, such as this
statement:

var iValue1;

In cu
rrent JScript, variables can change their type at will, for example:

var myVar = 3

myVar = “Helo World”

JScript.NET doesn't allow this with variables which have a declared data type. If no type is
specified, the variable is assumed to be of type Object. Un
initialized non
-
typed variables take
“undefined”


as their value, while number variables are forced to NaN and strings defaults to
the empty string.

The type
-
aware syntax for declaring functions is similar and looks like this:

function FuncName(param1 : in
t) : String

{...}

In this example param1 : int declares the data type required for this parameter, and : String
declares the data type which the function will return.

Type Inferencing

Handling of type
-
declared variables is optimized by the JScript.NET comp
iler. For untyped
variables the compiler uses an interesting optimization technique called type inferencing, in
which it attempts to guess which type of data you will be putting in the variable, and
optimises accordingly.

Effective type inferencing is is d
ependent on two things. First, the variable must be local, not
global. For this reason, always declare variables with a var statement, since variables which
are implied into existence (for example ‘newVar = 5’ are considered global. The second
requirement
is that the variable must only be assigned values of a single type within your
code. With these criteria met, type inferencing becomes an “invisible” technology that can
significantly improve the performance of your scripts.

A touch of class

JScript.NET in
troduces three new statements: class, import and package. Class declares the
name of a class plus its internal variables, properties and methods. Here’s a simple example of
a class:

class CMyClass{

var Property1 : String;

var Property2 : int;

function CMyC
lass(param1 : String) {



this.Property1 = param1;

};

}

You create an object of a class in the same way as you create a JScript object today, for
example:

var myObj = new cMyClass(“Hello World”)

Using classes, however, gives JScript.NET code a number of c
haracteristics not present in
today’s JScript. First, you can make some of a class’s variables (properties) and functions
private, like this:

class CMyClass{

var Property1 : String;

private

var Property2 : int;

function CMyClass(param1 : String) {



this.
Property1 = param1;

}

}

Now Property2 is invisible to code outside the object, providing true encapsulation.

Property accessors

You can also declare property accessor (‘get’ and ‘set’) functions in a class, which are
automatically invoked when an externall
y visible property is read or written. Set functions are
especially useful for validating new values being assigned to properties. Here’s an example:

class CMyClass{

var Property1 : String;

private var Property2 : int;

function CMyClass(param1 : String) {



this.Property1 = param1;

};


function
set

Property1 (newProperty1 : string) {

if (newProperty1.length >= 4 {



Property1 = newProperty1



} else {



throw “Values for Property1 must be a least four characters long”



}

}

}

Now this code:

myObj.Propert
y1 = “Hi there!”

will work, but this statement:

myObj.Property1 = “OK!”

will generate an error.

By default, objects derived from classes don’t support expando properties (see
part 10

of this
series), so with the object created above, saying:

myObj.extraProperty = 55

will generate an error. This reduces flexibility, but also closes one of the biggest coding
-
error
loopholes in
JScript. If you want a class to support expando properties, just add ‘expando’ to
its declaration.

Inheritance

A class can also extend and inherit from an existing class. In this case, the keyword is
'extends'.

class CCustomer extends CPerson {...}

A key f
eature here is that, because Jscript.NET is a fully paid
-
up member of the .NET
framework, it can extend existing classes written in any other .NET language, from Visual
Basic.NET to C#. To do this, you need to use the second new statement, ‘import’.

The 'i
mport' statement enables access to external libraries and facilitates direct reference of
entities contained within a specified namespace.

// Import the namespace

import System.Drawing.Color

The import keyword is the JScript.NET equivalent of the C# 'using
'

keyword.

The third new statement in JScript is 'package', which creates a package of classes that can be
imported into external applications. You import a package through the import keyword, then
access its members by name. If a member name conflicts wit
h another declaration in the same
scope, you prefix the member with the package name.

Option Fast

'
Option Fast'
is a new JScript.NET compiler directive which trades improved performance for
reduced flexibility. In this mode, you can only use declared varia
bles, and cannot re
-
assign
them with different data types. Undeclared variables are flagged as errors at compile time,
because they don’t support type inferencing. In addition, you can’t update or delete predefined
properties of the built
-
in JScript object
s. Expando properties are banned, you must supply the
correct number of arguments to function calls, and you can’t use the
arguments

property
within a function.

To switch Option Fast on, you use a directive like this at the start of your script:

@set @opti
on(fast)

If that looks an extremely unfamiliar piece of


JScript code, don't worry
-

we'll be covering
compiler directives next time!


Summary

JScript.NET has a dual character. On the one hand it looks like the old faithful JScript, with
support for typele
ss variables and expando properties. On the other hand, it’s a fully
-
fledged
.NET player with support for classes, inheritance, threading and more. This makes
JScript.NET a language for just about everyone, the only current problem being that you can’t
use

it on the desktop until Windows Script Host.NET arrives.

JScript tutorial
-

part 12


In the
final part of our JScript tutorial we look at JScript directives, including the ones
that have been available since JScript 3.0, and the new ones which will arrive

with
JScript.NET.

Dino Esposito

explains.

JScript 3.0 (which shipped with Internet Explorer 4.0 and WSH 1.0) introduced a feature
called conditional compilation, which allows

you to ‘hide’ selected JScript statements from
script engines that don’t support them. Its main purpose is to let you use newly
-
released
JScript language features in your code without sacrificing compatibility with older JScript
implementations. However i
t’s also useful for managing debug statements, and for hiding
JScript features which aren’t supported by other scripting dialects such as Netscape’s
JavaScript.

Conditional compilation is normally enabled by using the @cc_on statement, although it’s
also s
witched on by the first occurrence of an @if or @set statement (see below for details).
Here’s an example, designed to run in any script
-
enabled browser:

<script>

/*@cc_on @*/

/*@if (@_jscript_version >= 3)




alert("Your JScript engine supports condition
al compilation ");

@else @*/




alert("To run conditional code you need Internet Explorer 4.0 or later.");

/*@end @*/

</script>

This example examines the system variable ‘@_jscript_version’, which contains the version
number of the script engine in use. I
f its value is 3.0 or later, the first alert() statement is
executed. If it’s not, then the second alert() is executed.

The specially
-
formatted comment markers (/*@, @*/ etc) are essential when writing code
which will run in a variety of browsers, as they
avoid script errors in clients which don’t
support conditional compilation. Non
-
conditional script engines will only ‘see’ the script
statements between @else @*/


and /*@end @*/, so in the above example NetScape
Navigator (and IE 3.0) would process the se
cond alert(). The ‘@else @*/ ‘ statement is
essential even when there’s no ‘else’ code to execute, as without it non
-
conditional browsers
will report a ‘nested comment’ script error.


You might, therefore, write something like this:

/*@if (@_jscript_versio
n >= 3)


alert("Your JScript engine supports conditional compilation.");

@else @*/


/*@end @*/

This will produce no output at all on browsers without JScript 3.0 or later. Comments aren’t
necessary in JScript written for the Windows Scripting Host, since

all versions of WSH
support conditional compilation.

The @if construct also supports an @elif (else if) keyword, as in this WSH example:

@if (@_jscript_version > 5.5)



WScript.Echo("You're running a beta!")

@elif (@_jscript_version >= 5)



WScript.Echo
("You're running the current release version")

@else



WScript.Echo("Update your WSH now!")

@end

The @else clause is mandatory when @elif is used, even when the code is not commented.

You can put as many script statements as you like in each each part of
an @if construct,
including ‘regular’ JScript if () and other flow
-
control statements. You can also declare
functions there, allowing you to create different versions of a function depending on the script
engine version. Here’s an example:

<script>

/*@if (
@_jscript_version >= 5.5)



function showDate(dateObj){



// Use JScript 5.5’s toDateString() method



alert(dateObj.toDateString()) }

@else @*/




function showDate(dateObj){



// Use standard date
-
to
-
display format



alert(dateObj) }

/*@end @*/

tod
ay = new Date()

showDate(today)

</script>

You can also use @if in a more ‘inline’ way, by embedding it into JScript statements. Here’s
an example:


WScript.Echo(@if (@_jscript_version > 5.5) "You're running a beta!"


@else " You're
running release code " @
end)

Here the @if is placed inside the Wscript.Echo() method call, and selects the string constant
to be displayed.

Conditional compilation variables

Conditional compilation can be extremely useful when you have to execute different code
depending on the u
nderlying platform, and a number of built
-
in conditional compilation
variables are available to help you determine what you’re running on. @_win32 is set to true
if the platform is Win32, with


@_win16, @_x86, @_mac, @_mc680x0, @_PowerPC and
@_alpha indica
ting other operating system and processors, so you might say:

/*@if (@_mac)



// Generate page content without ActiveX control

and so on. The current JScript engine version is stored in @_jscript_version, in major.minor
format.

You can also create your ow
n conditional compilation variables, using the @set statement like
this:

@set @showmessages


= true

This example creates a variable called ‘@showmessages’, and assigns it a value of true (only
numeric and boolean values are allowed for conditional variable
s). You can examine (and
update) the variable’s value elsewhere in the document, for example:

@if (@showmessages)



Wscript.Echo("Stopped in main function”)

@end

You can also access conditional compilation variables from ordinary JScript statements, so
th
is code:

WScript.Echo("showmessages set to “ + @showmessages)

is valid.

New JScript.NET Directives

JScript.NET has three new conditional compilation features, mostly designed to help with
debugging and tracing. They are:



@debug





@option




@position

@debug
is a system variable, which you can set to ‘on’ and ‘off’ through the @set statement,
like this:

@set @debug(off)

@debug is set to ‘on’ by default, and controls the output of debug symbols such as those
produced by the ASP.NET runtime. If you don’t want de
bug symbols to be slipstreamed in
your code, set @debug to off.

The @position directive is the key to providing meaningful statement position information in
error messages. It's required because the line number reported in a script engine error message
may

be different from the erroneous statement’s position in the original source file. This is
because external modules (such as the ASP.NET runtime) can inject extra code into the script.
To resolve this problem, you can use @position to set absolute line and

file information. For
example,


@set @position(line = 1)

makes the runtime treat the source line that follows it as line number 1 when reporting errors,
irrespective of its position within the compiled code.

Here's the complete syntax of @position:

@set @
position(end |

[file = fname]

[, line = lnum]

[, column = cnum])

You can set where the code ends through the
end

keyword, as well as specifying the source
file name with or without drive and path information.


You can also set an absolute column
position.


Option Fast

The third new JScript.NET directive is @option. It makes the compiler treat script code in a
special way that limits flexibility, but increases performance. To invoke this feature, place this
statement at the start of yourv script code:

@set @
option(fast)

When running in fast mode, the JScript.NET compiler imposes the following rules:



All variables must be declared (even if it’s not typed) and any undeclared variable
originates an error




Functions cannot be redefined




Predefined properties of b
uilt
-
in objects cannot be updated




Expando properties are not allowed on built
-
in objects




Function calls must supply the correct number of arguments




A function’s .arguments property cannot be accessed

Setting @option(fast) switches off many of the backwa
rds
-
compatibility features of
JScript.NET, forcing you to treat it more as a compiled language, and less as a interpreted
scripting dialect.

The End

DNJ Online’s JScript tutorial series has now reached its conclusion. I hope you've enjoyed it,
and that it’
s been worth the time and effort you’ve spent reading it.


For me at least, it’s been
great fun! Please feel free to contact me, Dino Esposito, at
dinoe@wintellect.com

or through
the Wintellect's Web site at
www.wintellect.com
.