Server-Side JScript in ASP

by Rob Locher

The purpose of this article is to better explain things you will need to know if you plan to write ASP pages that use server-side JavaScript, aka JScript, as the scripting engine.

Why Server-Side JScript at All? Why Not Just Use VBScript?

The simple answer to that question is that JScript, which will be called JavaScript for the rest of this article, is a vastly more powerful language than VBScript.  JScript is either fully object-oriented or pretty close to it, depending upon whom you ask, because it supports private members (encapsulation), a form of inheritance, and polymorphism.  It also offers structured error handling, while VBScript only offers the ridiculous On Error Resume Next construct.  If you doubt what I say, take the time to familiarize yourself with JavaScript, read Douglas Crockford's articles about JavaScript on his web site, and then return to this article.

Now I'm not saying that JavaScript is as good as Java or C#.  Those languages are somewhat more complex, but make it much easier to write good object-oriented code.  However, sometimes people are forced to work in "legacy" environments where only scripting engines are available.  In that case, I feel that JavaScript beats VBScript hands down.

However, it must be said that several bad decisions in the design of ASP do much to thwart skilled programmers attempting to use server-side JavaScript.  These decisions universally make life marginally easier for the beginning web programmer at the expense of a lot of trouble for more skilled programmers trying to make the most of the language.  (I call this the Visual Basic effect, in honor of the IDispatch interface.)


Problem: Visual InterDev is lousy.

Workaround: Use Visual Studio .NET instead!  You can create an "Empty Web Project" in either C# or VB.NET (the choice is irrelevant), and then add ASP files to it (add an "HTML Page" and then rename it to .asp).  Visual Studio .NET integrates seamlessly with many source control providers such as Visual SourceSafe, which is something you couldn't do at all with Visual InterDev.  You can turn on ASP debugging in the project properties dialog.  You also get the Copy Project wizard which is very handy for deployment.  There is one odd thing about using Visual Studio .NET to work on an ASP project, though; when you start debugging, Visual Studio will spend a split second compiling an empty DLL.  Weird.


Problem: ASP assumes that your server-side code is VBScript unless you tell it otherwise somehow.  This is especially a problem for include files, because you can't use a <%@ LANGUAGE="jscript" %> directive in an include file.  This throws off syntax highlighting in the IDE, which is very distracting.

Workaround: If you're using Visual Studio .NET instead of Visual InterDev (highly recommended), in the Visual Studio project settings set the "client" script language to JScript.  Otherwise, use <script runat="server" language="jscript"></script> blocks instead.


Problem: scripts delineated with <% %> run before scripts delineated with <script runat="server"></script> .  This makes it so your code isn't parsed in the order you expect.  If JavaScript comes across a function call for a function that hasn't been defined yet, it will search downwards through the code until it finds your function, which will be executed "for your convenience".  Unfortunately, if that function defines an object that has a prototype with methods that haven't been defined yet, you will be left to wonder why your method doesn't seem to exist.  It would be better if JavaScript would just raise an error saying that the function hasn't been defined yet.  Instead somebody made the unfortunate decision to do the simplest thing to avoid the easy error, giving instead an error much more difficult to track down, but only if you use prototypes.  (A lot of things in JavaScript are like that.)

Workaround: use either <% %> blocks or <script runat="server"></script> blocks, but not both, so that you control the order things are parsed and not ASP.  Make sure that the code to modify an object's prototype parses before the code that creates an instance of the object.