Just JavaScript - Life Without Type - Duck Testing And Prototype Construction
Written by Ian Elliot   
Thursday, 07 May 2015
Article Index
Just JavaScript - Life Without Type - Duck Testing And Prototype Construction
Prototype Testing
Prototype Constructor
Prototype as Interface

Attempts to impose type on JavaScript just don't seem to work unless you turn JavaScript into a completely different language. We have already embarked on a consideration of how to live without type in JavaScript and now we move on to dealing with realtime type checking.

Just JavaScript 

 There is a newer version of the draft of the book here.

A Radical Look At JavaScript

Contents

  1. JavaScript Isn't Java, or C, or C# ... (Book Only)
  2. In The Beginning Was The Object
  3. The Function Object
  4. How Functions Become Methods
  5. The Object Expression
  6. Object Construction
  7. The Prototype
  8. Type And Non-Type
  9. Constructor And InstanceOf
  10. Duck Testing And Prototype Construction

-Preface-

Most books on JavaScript either compare it to the better known class based languages such as Java or C++ and even go on to show you how to make it look like the one of these.

Just JavaScript is an experiment in telling JavaScript's story "just as it is" without trying to apologise for its lack of class or some other feature. The broad features of the story are very clear but some of the small details may need working out along the way - hence the use of the term "experiment". Read on, but don't assume that you are just reading an account of Java, C++ or C# translated to JavaScript - you need to think about things in a new way. 

Just JavaScript is a radical look at the language without apologies. 

JustJavaScripticon

 

 

Type is all about characterizing the properties an object has.

This works in different ways at compile time and at runtime.

JavaScript doesn't really support the concept of type but this doesn't stop programmers from trying to invent it and all of the mechanism of class based inheritance and type. 

In this chapter we look at alternatives to type both at runtime and compile time. In other languages type is mostly about finding errors before the program runs, but in JavaScript the emphasis is usually placed on runtime because this is where the objects are - not to mention it doesn't really have a compile time. In JavaScript the best alternative to compile time type checking is to get the editor to check.

In the first part of this chapter we look at runtime alternatives to type in JavaScript. 

Even in the case of a class based language making use of type at runtime is difficult and often tackled using mechanisms like reflection and metadata. When a programmer asserts that strong typing reduces errors they are usually thinking about compile time mistakes. A runtime type error usually results in an exception and this is true in JavaScript.

The subtle point of compile time type checking is that it can provide an assurance that everything is ok at run time. If you have a variable of a given type and you don't cast it to another type then you can be fairly sure that if it passes compile time checks then it will be ok at runtime.

However without compile time type checking all type checking in JavaScript is going to be runtime type checking. 

There is an alternative to trying to reinvent runtime type in JavaScript. As the only purpose of establishing the type of an object is to be sure what properties it has - why not forget type and concentrate on the properties with duck testing.

In some situations this is by far the best thing to do but occasionally the need to test many properties becomes unwieldy and we need a better way. Once again it is time to go back to the role of prototype inheritance which can be used to test for the possession of large sets of properties very efficiently. To make it work elegantly we need to take a slightly different approach to object construction - the prototype constructor. 

Why So Much Runtime Type Testing?

In a class based language much of the type checking occurs at compile time and this provides a measure of protection at runtime.

For example, if you declare a variable to be of one type and you try and make it reference an incompatible type you will generate a compiler error:

MyClass myvar=new SomeOtherClass();

Assuming that SomeOtherClass isn't a subclass of MyClass then this program will never get to run because the compiler will throw up a type error. 

In the same way in a class based language any attempt to use a property that isn't defined within the declared type is flagged up at compile time. For example,

String mystring=new String("Hello World"):
mystring.random();

will never get to run because the compiler will complain that a String doesn't have a random method (assuming it doesn't of course). 

There is no compile stage for JavaScript and what is more variables aren't typed. 

So the first typical error i.e. assigning the wrong type to a variable can't happen at any time.

However the second common error does happen in JavaScript but it can't be flagged at compile time because there is no compile time. Instead if you run the JavaScript equivalent:

var mystring=new String("Hello World"); mystring.random();

You will see a runtime error telling you that random is an undefined property and not a function.

So many errors that are detected at compile time in class based languages are detected at runtime in JavaScript. 

However as long as they are detected while you are testing the program they are just as easy to understand and just as easy to fix. The reason is that they are static errors - mystring is a String and you can deduce this just by reading the code. As you know a String doesn't have a random method you can see the code is incorrect. You don't need to run the program to know that there is an error. 

Of course there are some errors are not detectable at compile time because the type of the object being referenced isn't determined until runtime i.e. the type is dynamic and in this case the only possibility is runtime detection. 

Any runtime testing you include in JavaScript has at least the advantage of working in all cases. 

Forget Type - Use Duck Testing

If you have reached this point and feel that something is lacking in trying to recreate type in JavaScript then you might like to consider the alternative - duck testing. 

This idea is core to JavaScript's approach to objects. 

If it walks like a duck and quacks like a duck then it is a duck.

You could say more accurately that it is enough of a duck for our purposes.

If you want to check if an object has a set of properties then why not just test to see if it has - i.e. test to see if if quacks.

This is very easy, works without complication and works at runtime. 

For example suppose you are passed an object and you want to use prop. If prop hasn't been defined on the object or its prototype chain then 

obj.prob

is undefined so you can test. 

if(obj.prop===undefined) then object isn't usable

This is easy and unless you are testing lot of properties repeatedly it is efficient. If you are checking lots of properties repeatedly just do it once and set a validated property so that you don't do it again. 

The is one additional problem the property might exist i.e. might be defined but it might have the wrong type of value. 

This usually occurs when you do something like this:

if(obj.method!==undefined) alert(obj.method());

only to discover a runtime exception because method isn't a function object and so cannot be called. 

This is where primitive type enters the picture. 

Testing Primitive Type - typeof

The typeof operator will return a string that gives the primitive type of an object.  

Mozilla lists the following results for typeof:

TypeResult
Undefined "undefined"
Null "object" 
Boolean "boolean"
Number "number"
String "string"
Symbol (new in ECMAScript 6) "symbol"
Host object (provided by the JS environment) Implementation-dependent
Function object (implements [[Call]] in ECMA-262 terms) "function"
Any other object "object"

 

This seems reasonable apart from perhaps Null being an object. Unfortunately not all browsers implement the strict definition of a function object as something you can call. In particular Chrome to version 12 defined a regular expression as a function. 

Using typeof you can test to see not only that a property exists but that it is of the correct type. For example:

if(typeof(obj.method)==="function") 
                     alert("it is a function");

This tests that obj.method exists and that it is a function. If it doesn't exist typeof returns the string "undefined".

An alternative and slightly more secure method for a Function object is to test first to see if the property exists and then test to see if the constructor is what you expect.  For example:

if(obj.method!==undefined){  alert(obj.method.constructor===Function); 
};

This first tests that method exists and then that it  is a function by checking the constructor. 

You can use this method for general objects where you set a custom constructor as long as you always remember to set the constructor property. 



Last Updated ( Tuesday, 25 August 2015 )