Tuesday, January 8, 2013

Javascript Object/Variable type detection


            This articles discusses about discovering the type of variables/objects in javascript, we can also look into Javascript (and Ecmascript)basics. A loosely type programming language is one which does not require us to define a type for a variable to hold values.

var a;
a = 1;       
alert(a);    // 1
a = "Test";
alert(a);   //  Test
a=null;
alert(a);   //  null

The above example shows us that javascript is a loosely typed language. So now this gives the freedom to easily assign values to those variable without having to care about their type. But we do face situations where we need to know the type of the variable we are dealing with, so how does javascript handle the situation ?

There are many ways of doing this, lets look upon them one by one

1) instanceof

The very basic method is to use the 'instanceof' operator. It is used to test whether the argument supplied to  it belongs to a particular type. It returns either true or false. It works well for variables created by constructors but not for most literals.

new String('test') instanceof String     //true
'abc' instanceof String                  //false

new Number(10) instanceof Number         //true
10 instanceof Number                     //false

new Boolean('true') instanceof Boolean   //true
true instanceof boolean                  //false

2) typeof

The next method is to use 'typeof'. The typeof operator takes an argument in front and returns the type of the argument as a response string.

typeof 999          // Number
typeof 'test'       // String
typeof function(){} // Function
typeof true         // boolean

But the disadvantage with typeof operator is that

It fails with Arrays
typeof ['abc', 'def', 'ghij', 21]; // "object"
It returns only 'object' for all instance of the object which is not useful
typeof new String('test'); // "object"
typeof new Date();         // "object"
typeof new Number(999);    // "object"
typeof new Boolean(true);  // "object"
It fails with most of the core objects
typeof Math;    // "object"
typeof Array;   // "function"
typeof Number;  // "function"
typeof Object;  // "function"

Note:
typeof operator on null returns object. This is because it the result specified in the standard table for null. Brendan Eich felt that 'null' mostly used with object unlike 'undefined' and hence added this entry to the standard table to return 'object' although ECMA-262-3 standard defines type of null as Null.

3) duck typing

The 'typeof' and 'instanceof' are of not too useful and thus has forced us to follow 'duck typing'.

Wikipedia states 'duck typing is a style of dynamic typing in which an object's methods and properties determine the valid semantics, rather than its inheritance from a particular class or implementation of a specific interface'

Duck testing -  If it looks like a duck, swims like a duck, and quacks like a duck, then it probably is a duck.

Similarly if the object can identified by testing if it responds to particular methods. This requires us to define unique methods for every object to identify them easily,
for ex:
In java script

function isString(arg) {
  return arg.charAt !== undefined;
}
function isArray(arg) {
return arg.pop !== undefined;
}

We pass the argument and test if the object contain the properties, and return the corresponding results. This is a better way of testing for objects types than instanceof or typeof.
However if we resort to duck typing we may have to write a function for every different type or if we have a single function to check for types, we may have to add new checks for new classes. This is a disadvantage of duck typing when we want to have a generic solution.

4) Object prototype method -toString(args)

One of the best and recommended ways to discover variable type is to use the core object, Object's prototype method - toString(arg). It checks and returns the type of the argument.

Object.prototype.toString('abc'); // "[object String]"
Unlike 'typeof' it works both with instances of core objects (created with constructors) and with literals
Object.prototype.toString(new String('test')); // " [object String]"
Object.prototype.toString('test'); // "[object String]"

Object.prototype.toString(new Number(999)); // " [object Number]"
Object.prototype.toString(999); // " [object Number]"

Unlike 'typeof' it can also (native) objects such as Math and Date

Object.prototype.toString(Math);       // " [object Math]"
Object.prototype.toString(new Date()); // " [object Date]"

Unlike duck typing we need not add functions or new checks for classes as we can have a single function that takes any arguments and returns the get the type of the  returned.

Thus core object, Object's prototype method - toString(args) proves to be a better solution when we need to determine the type of a javascript variable/object.

Note:
Ecmascript has totally 9 datatypes, out of which only 6 are directly accessible in the language,
  1. Undefined
  2. Null
  3. String
  4. boolean
  5. Number
  6. Object
Everything except the object are represented in implementation directly on a low level in the language. They do not have any properties or constructors.
Objects on the other hand are collection of un ordered set of key, value pairs. Each object has properties and constructor. They are the only type that represents the Ecmascript objects. The keys represent the properties and the value can either be primitives, other objects or function (called as object's method).

the other 3 that can be realized in the language are
  1. Reference
  2. List
  3. Completion   
Reference is used during the use of operators such as 'delete', 'typeof' and consists of a base object.
List describes the behaviour of argument list, such as in new and function calls.
Collection type is used in explanation of break, continue, throw statments.


References and Sources -


Javascript vs Ecmascript - http://stackoverflow.com/questions/912479/what-is-the-difference-between-javascript-and-ecmascript
http://www.examplejs.com/?tag=object-prototype-tostring
http://www.youtube.com/watch?feature=player_embedded&v=v2ifWcnQs6M

No comments:

Post a Comment