JavaScript - Type Checking

javascript

// JavaScript - Type checking

There are 3 different ways to implement type checking:
1. Using the typeof operator
2. Using the instanceof operator
3. Using the constructor property

// null is considered as object.
var bar = null;
console.log(typeof bar === "object");  // logs true!
console.log(typeof Boolean(0)) // boolean
console.log(typeof Number(0)) // number

// To use the typeof operator appropriately to check for object
(bar !== null) && (typeof bar === "object")

// Arrays are also considered as object

var k = function(){};
console.log(typeof k);  // logs function!

// If bar is a function, then typeof bar returns 'function'. In most cases, this 
// is the desired behavior, but in situations where you want to also return true 
// for functions, you could amend the above solution to be:
(bar !== null) && ((typeof bar === "object") || (typeof bar === "function"))

// If bar is an array, then typeof bar returns 'object'.  In most cases, this is 
// the desired behavior, since arrays are indeed objects, but in situations 
// where you want to also false for arrays, you could amend the above solution 
// to be:
(bar !== null) && 
  (typeof bar === "object") && (toString.call(bar) !== "[object Array]")

// Checking to see if a variable is an array:
if( Object.prototype.toString.call( arrayList ) === '[object Array]' ) {
    console.log('Array!');
}

// null == undefined is true

// If var a = 2, b =3 what would be value of a && b is 3.

// 42..toString() is "42", but 4.2..toString() is a syntax error.

// typeof(NaN) is 'number'

// To implement type-checking using the typeof operator:

The typeof operator gives us a string representing the type of a variable.  
This would be the perfect solution except for variables of type object or array, 
or a custom object, in which case, it only returns 'object', making it hard to 
differentiate between objects.

if (typeof(varname) == "string") {
}

The value produced by the typeof operator are 'number', 'string', 'boolean', 
'undefined', 'function', 'object'.  If the operand is an array or null, the 
the result is 'object', which is wrong.

// Problem with instanceof:

"foo" instanceof String => false, 
1 instanceof Number => false, 
{} instanceof Object => false

"foo" instanceof String => false is correct, because typeof "foo" == 'string'.
new String("foo") instanceof String => true, because typeof String == 'function'.
You should treat function like class (definition of class). Variable become 
instanceof some function (class) when you assign it as var 
v = new AnythingWhatTypeofEqualsFunction(). The same applies to 1. 
typeof 1 == 'number' - 'number' is not 'function'.
{} instanceof Object is TRUE in node and modern browsers

Every object in JavaScript has a prototype, accessible through the __proto__ 
property. Functions also have a prototype property, which is the initial 
__proto__ for any objects created by them. When a function is created, it is 
given a unique object for prototype. The instanceof operator uses this 
uniqueness to give you an answer. 

Note that you can reassign any object to a function's prototype property, and 
you can reassign an object's __proto__ property after it is constructed.

// To implement type-checking using the constructor property:

Another way to check the type of an object is by referencing a property of all 
JavaScript objects called 'constructor'.  This property is a reference to the 
function used to originally construct this object.

if (varname.constructor == String) {
}

Refer to page 24 of "Pro JavaScript Techniques" for a table comparing the 
differences between typeof and .constructor.

// To implement type-checking using the instanceof operator:

var myArray = [];
if (myArray instanceof Array) {
   // do something...
}

We can also build a generic function for doing type-checking with a function:

// Strictly check a list of variable types against a list of arguments
function strict( types, args ) {
  // Make sure that the number of types and args matches
  if ( types.length != args.length ) {
    throw "Invalid number of arguments.  Expected " + types.length 
      + ", received " + args.length + " instead.";
  }
  // Go through each of the arguments and check their types
  for ( var i = 0; i < args.length; i++ ) {
    if ( args[i].constructor != types[i] ) {
      throw "Invalid argument type.  Expected " + types[i].name 
        + ", received " + args[i].constructor.name + " instead.";
    }
  }
}

// A simple function that use the above function to do type-checking
function userList (prefix, num, users ) {
  // Make sure that the prefix is a string, num is a number, 
  // and users is an array
  strict( [ String, Number, Array ], arguments );
  // blah blah
}
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License