The JScript Type System, Part Two: Prototypes and constructors

A number of readers made some good comments on my article on JScript typing that deserve to be called out in more detail.


First, I was being a little sloppy in my terminology — I casually conflated static typing with strong typing, and dynamic typing with weak typing. Thanks for calling me on that. Under the definitions proposed by the reader, JScript would be a dynamically typed language (because every variable can take a value of any type) and a strongly typed language (because every object knows what type it is.) By contrast, C++ is a statically typed language (because every variable must have a type, which the compiler enforces) but also a weakly typed language (because the reinterpret cast allows one to turn pointers into integers, and so on.)


Second, a reader notes that one of the shortcomings of JScript is that though it is a strongly typed language (in our new sense) that it is a royal pain to actually determine the runtime type an object. The typeof operator has a number of problems:


* null is listed as being of the object type, though technically it is a member of the Null type.

* primitives (strings, numbers, Booleans) wrapped in objects are listed as being of the object type rather than their underlying type.

* JScript, unlike VBScript, does not interrogate COM objects to determine the class name.

* If JScript is passed a variant from the outside world that it cannot make sense of then typeof returns “unknown”.


Perhaps there is some other way. Prototype inheritance affords a kind of type checking, for example.


Prototype inheritance works like this.  Every JScript object has an object (or possibly null) called its prototype object.  So suppose an object foo has prototype object bar, and bar has prototype object baz, and baz has prototype object null.  If you call a method on foo then JScript will search foo, bar and baz for that method, and call the first one it finds. The idea is that one object is a prototypical object, and then other objects specialize it. This allows for code re-use without losing the ability to dynamically customize behaviour of individual objects.


Prototypes are usually done something like this:


var Animal = new Object();

// omitted: set up Animal object

function Giraffe(){

// omitted: initialize giraffe object.


Giraffe.prototype = Animal;

var Jerry = new Giraffe();


Now Jerry has all the properties and methods of an individual Giraffe object AND all the properties and methods of Animal.  You can use IsPrototypeOf to see if a given object has Animal on its prototype chain. Since prototype chains are immutable once created, this gives you a pretty reliable sort of type checking.


Note that Giraffe is not a prototype of Jerry. Note also that Animal is not the prototype of Giraffe! The object which is assigned to the prototype property of the constructor is the prototype of the instance.


Now, you guys are not the first people to point out to me that determining types is tricky. A few years ago someone asked me what the differences are amongst


if (func.prototype.IsPrototypeOf(instance))




if (instance.constructor == func)




if (instance instanceof func)


The obvious difference is that the first one looks at the whole prototype chain, whereas the second two look at the constructor, right? Or is that true? Is there a semantic difference between the last two? Actually, there is. Let’s look at some examples, starting with one that seems to show that there is no difference:


function Car(){}

var honda = new Car();

print(honda instanceof Car); // true

print(honda.constructor == Car);  // true


It appears that instance instanceof func and instance.constructor == func have the same semantics.   They do not.  Here’s a more complicated example that demonstrates the difference:


var Animal = new Object();

function Reptile(){ }

Reptile.prototype = Animal;

var lizard = new Reptile();

print(lizard instanceof Reptile); // true

print(lizard.constructor == Reptile); // false


In fact lizard.constructor is equal to Object, not Reptile.


Let me repeat what I said above, because no one understands this the first time — I didn’t, and I’ve found plenty of Javascript books that get it wrong. When we say


Reptile.prototype = Animal;


this does NOT mean “the prototype of Reptile is Animal”.  It cannot mean that because (obviously!) the prototype of Reptile, a function object, is Function.prototype.  No, this means “the prototype of any instance of Reptile is Animal”.  There is no way to directly manipulate or read the prototype chain of an existing object.


Now that we’ve got that out of the way, the simple one first:


instance instanceof func means “is the prototype property of func equal to any object on instance’s prototype chain?”  So in our second example, the prototype property of Reptile is Animal and Animal is on lizard’s prototype chain.


But what about our first example where there was no explicit assignment to the Car prototype?


The compiler creates a function object called “Car”.  It also creates a default prototype object and assigns it to Car.prototype.  So again, when we way


print(honda instanceof Car);


the instanceof operator gets the prototype property (Car.prototype) and compares it to the prototype chain of honda.  Since honda was constructed by Car it gets Car.prototype on its prototype chain.


To sum up the story so far,

Tags JScript Scripting

Comments (16)

Cancel reply

You must be logged in to post a comment.

  1. Erik Arvidsson says:Just a side note. The prototype object is usually called __proto__ ( [[Protoype]] in the spec) and almost all ECMAScript engines (except the Microsoft ones) allows read write of this private property.
  2. Log in to Reply
  3. November 6, 2003 at 2:40 pm
  4. Jay Hugard says:Can you explain the logic behind the following madness (in JScript Classic), which appears to mean that a string is not always a String but a regexp is always a RegExp?slit instanceof String => false
    sobj instanceof String => true
    slit instanceof Object => false
    sobj instanceof Object => true
    typeof( slit ) => string
    typeof( sobj ) => object
    typeof( slit ) == typeof( sobj ) => falseAs generated by:function evalprintln( s )
    if( !s ) { println(“”); return }
    var out = s + ” => “;
    try{ out += eval(s) } catch( e ) { out += “Error: ” + e.description }
    }var tests = [
    “slit instanceof String”,
    “sobj instanceof String”,
    “slit instanceof Object”,
    “sobj instanceof Object”,
    “typeof( slit )”,
    “typeof( sobj )”,
    “typeof( slit ) == typeof( sobj )”,
    “relit instanceof RegExp”,
    “reobj instanceof RegExp”,
    “relit instanceof Object”,
    “reobj instanceof Object”,
    “typeof( relit )”,
    “typeof( reobj )”,
    “typeof( relit ) == typeof( reobj )”
    ];Log in to Reply
  5. for( var ix in tests ) { evalprintln( tests[ix] ) }
  6. var slit = “Literal String”;
    var sobj = new String( “String object” );
    var relit = /literal regexp/i
    var reobj = new RegExp( “RegExp object” );
  7. function println(s) { WScript.echo(s) /*System.Console.Out.WriteLine(s)*/ }
  8. relit instanceof RegExp => true
    reobj instanceof RegExp => true
    relit instanceof Object => true
    reobj instanceof Object => true
    typeof( relit ) => object
    typeof( reobj ) => object
    typeof( relit ) == typeof( reobj ) => true
  9. Conversly, what is the recommended way of determining if a value is a string?
  10. November 6, 2003 at 6:01 pm
  11. Peter Torr says:Erik — IIRC, Netscape removed the support for __proto__ from their engine some years ago because it was a bad idea to let people mess with the prototype chain this way. The ECMA standard does not require the property to be exposed, and it is dangerous to do so.
  12. Log in to Reply
  13. November 6, 2003 at 6:32 pm
  14. Peter Torr says:Jay, if you read the ECMA spec you will see that there are string primitives and string objects, just as there are number/boolean primitives and number/boolean objects. Basically you should never use “new String(…)” because it is a waste of time and energy.print(nlit instanceof Number)
    print(nlit instanceof Object)
    print(nobj instanceof Number)
    print(nobj instanceof Object)
  15. Log in to Reply
  16. var nlit = 42
    var nobj = new Number(42)
  17. November 6, 2003 at 6:40 pm
  18. IUnknown says:>JScript, unlike VBScript, does not interrogate COM objects to determine >the class name.Log in to Reply
  19. This gets the award for the most unrelated error message:
    throws, when the type information is unavailable:
    Out Of string space: ‘TypeName’
  20. November 7, 2003 at 2:02 am
  21. Eric Lippert says:Can I see a repro for that? If the type name is unavailable, it should return “Unknown” or, if it is an IDispatch, “Object”.Log in to Reply
  22. TypeName does return “Out of string space”, but only when the attempt to allocate the string for the type name fails.
  23. November 7, 2003 at 12:54 pm
  24. Erik Arvidsson says:Peter: I know both the Mozilla engines (C and Java) and the Macromedia engine has support for this. I was pretty sure that Opera supported this as well but I just verifed that they do not.fucntion SubClass( args )
    { args );
    SubClass.prototype.__proto__ = SuperClass.prototype;Log in to Reply
  25. Well, well… now that we have ECMAScript v4 around the corner there is no real need for this.
  26. I can understand why it is considered dangerous but usage of __proto__ can be very useful. For example it allows you to skip creating an instance that is used as the prototype.
  27. November 7, 2003 at 3:14 pm
  28. Eric Lippert says:> Well, well… now that we have ECMAScript v4 around the corner there is no real need for this.Log in to Reply
  29. That’s news to me. Could you more precisely define “around the corner”?
  30. November 7, 2003 at 5:02 pm
  31. Isaac says:> conflated static typing with strong typing
    “static typing” unhelpfully confuses when checks are made with the kind of checks that are made.Simpler to understand that JScript is a dynamically-checked untyped (safe?) language.Log in to Reply
  32. I think you demonstrated that it’s pretty hard to figure out what the type of a value is in JScript – so why insist on calling it a typed language?
  33. Simpler to understand that C++ is a statically-checked weakly-typed language (and also that some things are dynamically checked in C++).
  34. November 7, 2003 at 5:26 pm
  35. Anonymous says:[quote]Can I see a repro for that? If the type name is unavailable, it should return “Unknown” or, if it is an IDispatch, “Object”. [/quote]Also see this:
  36. Log in to Reply
  37. I got this when trying it on a COM object that uses run-time generated type info (ie. CreateDispTypeInfo). This only provides a minimal implementation of ITypeInfo. This is not common(or recommended) so I wouldn’t worry too much. If it helps the COM object is out of process.
  38. November 8, 2003 at 6:05 am
  39. Eric Lippert says:OK, then I have a guess as to what is happening. This is a TERRIBLE way to wait for an out-of-proc object (OOPO) to shut down. I’ll bet that there is a race condition here where the stub is returning a pointer to memory that becomes bad when the OOPO shuts down. So the TypeName method essentially gets passed a pointer to bad memory.So what we’ve got here is a memory corruption bug that is not crashing, but returning a bogus error instead.
  40. Log in to Reply
  41. Now suppose that the bad memory happens to be in a readable committed page, but contains garbage. We assume that the thing is a BSTR, so we look at the value stashed preceding the string body to determine the length. That could be any old number; the odds that the number happens to be larger than the largest remaining heap block are actually very good.
  42. November 8, 2003 at 10:57 am
  43. Anonymous says:The link I posted was just something I found while searching on the error. My situation relates to using run time type info. Have you tested TypeName with run time type info? It is obsolete and I only use it for testing so this discussion is essentially accademic.I think my object was based on the code found here, so if you want to copy and paste:
  44. Log in to Reply
  45. My guess is that something similar is happening, ITypeInfo must be returning bogus data. Assuming that you check all error results this could even be a bug in the implementation of ITypeInfo for CreateDispTypeInfo. As mentioned, this is obsolete and probably hasn’t been looked at for a long time.
  46. November 9, 2003 at 4:13 am
  47. Erik Arvidsson says:”That’s news to me. Could you more precisely define “around the corner”?”Known implemantions of ECMAScript v4:One possible reason for JS2 taking so long might be that ECMA moved all their resources to C# instead?
  48. Log in to Reply
  49. ActionScript


    JScript 7

  50. I guess I was wrong 😥 This has been in the works for way too long…
  51. May 2, 2004 at 7:07 am
  52. Eric Lippert says:A more likely reason is that Waldemar Horwat, who was the primary driving force behind the E4 spec, no longer works for AOL-Time-Warner-Netscape and hence is no longer being paid to drive the spec process forward. (Rumour has it that he’s at google now.)Log in to Reply
  53. Microsoft is still involved in the E4 process, but it is slow going.
  54. May 2, 2004 at 8:23 am
  55. Fabulous Adventures In Coding says:Log in to Reply
  56. October 7, 2004 at 1:32 pm
  57. Intercept instanceof | keyongtech says:PingBack from
  58. Log in to Reply
  59. January 18, 2009 at 12:41 pm

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s