The JScript Type System Part Seven: Yeah, you've probably guessed that I wrote the array stuff

The JScript Type System Part Seven: Yeah, you've probably guessed that I wrote the array stuff

  • Comments 3

A reader asked me to clarify a point made in an earlier entry:


Note that JScript .NET arrays do not have any of the methods or properties of a CLR array. (Strings, by contract, can be used implicitly as either JScript .NET strings or as System.String values, which I'll talk more about later.) But JScript .NET arrays do not have CLR array fields like Rank, SetValue, and so on.


It's actually pretty straightforward.  When you have a string in a JScript .NET program, we allow you to treat it as both a System.String and as a JScript object with the String prototype.  For example:


var s = "   hello   ";

print(s.toUpperCase()); // calls JScript string prototype's toUpperCase

print(s.Trim()); // calls System.String.Trim


Which is it?  From a theoretical standpoint, it doesn't really matter -- you can use it as either.  From an implementation standpoint, of course we use System.String internally and magic up the prototype instance when we need one -- just as in JScript classic all strings are VT_BSTR variants internally and we magic up a wrapper when we need one.  So JScript strings and CLR strings really are totally interoperable.


Arrays aren't quite so seamless.  As I mentioned earlier, when you try to use a JScript .NET array when a CLR array is expected, we create a copy.  But when you go the other way, things are a little different. Rather than producing a copy, using a CLR array as a JScript .NET array "wraps it up". No copy is made. The operation is therefore efficient and preserves identity. Changes made to a wrapped array are preserved:


function ChangeArray(arr : Array) : void


  print(arr[0]); // 10

  arr[0] += 100;

  // JScript .NET methods work just fine

  print(arr.join(":")); // 10:20:30


var arr : int[] = [10, 20, 30];


print(arr[0]); // 110


The principle rule for treating a hard-typed array as a JScript .NET array is that it must be single-dimensional. Since all JScript .NET arrays are single-dimensional it makes no sense to wrap up a high-rank CLR array.


Once the array is wrapped up it still has all the restrictions that a normal hard-typed array has. It may not change size, for instance. This means that an attempt to call certain members of the JScript .NET Array prototype on a wrapped array will fail. All calls to push, pop, shift, unshift and concat as well as some calls to splice will change the length of the array and are therefore illegal on wrapped CLR arrays.


Note that you may use the other JScript .NET array prototype methods on any hard-typed array (but not vice versa). You can think of this as implicitly creating a wrapper around the CLR array, much as a wrapper is implicitly created when calling methods on numbers, Booleans or strings:


var arr : int[] = [10, 20, 30];

arr.reverse();    // You may call JScript .NET methods on hard-typed arrays

print(arr.join(":"));   // 30:20:10


There may be a situation where you do want to make a copy of a CLR array rather than wrapping it. JScript .NET has syntax for this, namely:


var sysarr : int[] = [10, 20, 30];

var jsarr1 : Array = sysarr; // create wrapper without copy

var jsarr2 : Array = Array(sysarr); // create wrapper without copy

var jsarr3 : Array = new Array(sysarr); // not a wrapper; copies contents


In the last case jsarr3 is not a wrapper. It is a real JScript .NET array and may be resized.

  • I think some of that reader's misunderstanding is a result of the use of the word "contract" where the word "contrast" was intended. In any event, thanks for the info. A question though: suppose I had changed the ChangeArray implementation to: function ChangeArray(arr) : void { print(arr[0]); // 10 arr[0] += 100; } Would it still convert the CLR array to a JScript.NET array? Or have I created a generic function that works for both types with no conversions?
  • Dan, your changed function does not specify a type for the 'arr' parameter, so it will be compiled as "Object" and all operations on 'arr' will be late-bound. Thus it will work with JScript arrays, CLR arrays, and indeed anything that has an overloaded indexing operator.
  • Yeah, I guess the spell checker didn't catch that one, did it? :-)
Page 1 of 1 (3 items)