tags:

views:

899

answers:

6

I have an annoying bug in on a webpage: "date.GetMonth() is not a function". So I suppose that I am doing something wrong since somewhere and the object date is not an object of type Date. How can I check for a datatype in Javascript? I tried to add a if(date) but it doesn't work.

function getFormatedDate(date) {
    if (date) {
       var month = date.GetMonth();
    }
}

So if I want to write defensive code and prevent the date (which is not one) to be formatted, how do I do that?

Thanks!

UPDATE: I don't want to check the format of the date, but I want to be sure that the parameter passed to the method getFormatedDate is of type Date.

+8  A: 

The function is getMonth(), not GetMonth().

Anyway, you can check if the object has a getMonth property by doing this. It doesn't necessarily mean the object is a Date, just any object a getMonth property.

if (date.getMonth) {
    var month = date.getMonth();
}
Chetan Sastry
Aw, you beat me to it. Oh well.
R. Bemrose
This only checks that it has getMonth property of some type, doesn't check if it's callable.
vartec
@vartec: Fixed the description. Christoph's answer is more accurate.
Chetan Sastry
+2  A: 

You could check if a function specific to the Date object exists:

function getFormatedDate(date) {
    if (date.getMonth) {
        var month = date.getMonth();
    }
}
R. Bemrose
A: 

As indicated above, it's probably easiest to just check if the function exists before using it. If you really care that it's a Date, and not just an object with a getMonth() function, try this:

function isValidDate(value) {
    var dateWrapper = new Date(value);
    return isNaN(dateWrapper.getDate());
}

This will create either a clone of the value if it's a Date, or create an invalid date. You can then check if the new date's value is invalid or not.

bdukes
+14  A: 

As an alternative to duck typing via

typeof date.getMonth === 'function'

you can use the instanceof operator, i.e.

date instanceof Date

This will fail if objects are passed across frame boundaries.

A work-around for this is to check the object's class via

Object.prototype.toString.call(date) === '[object Date]'
Christoph
Out of interest do you know the reason for this failing when passing across frame boundaries?
Simon Lieschke
@Simon: JS globals are local to the current global object (aka `window` or `self`); different frames have their own global objects, and their properties (ie globals) refer to distinct objects: `Date` in frame1 is a different function object than `Date` in frame2; the same is true for `Date.prototype`, which is the reason for the `instanceof` failure: `Date.prototype` from frame1 is not part of the prototype chain of `Date` instances from frame2
Christoph
A: 

Actually date will be of type Object. But you can check if the object has getMonth method and if it is callable.

function getFormatedDate(date) {
    if (date && date.getMonth && date.getMonth.call) {
       var month = date.getMonth();
    }
}
vartec
Christoph's answer is more accurate. Having a 'call' property doesn't necessarily mean it is a function!
Chetan Sastry
+1  A: 

For all types I cooked up an Object prototype function. It may be of use to you

Object.prototype.typof = function(chkType){
      var inp        = String(this.constructor),
          customObj  = (inp.split(/\({1}/))[0].replace(/^\n/,'').substr(9),
          regularObj = Object.prototype.toString.apply(this),
          thisType   = regularObj.toLowerCase()
                        .match(new RegExp(customObj.toLowerCase()))
                       ? regularObj : '[object '+customObj+']';
     return chkType
            ? thisType.toLowerCase().match(chkType.toLowerCase()) 
               ? true : false
            : thisType;
}

Now you can check any type like this:

var myDate     = new Date().toString(),
    myRealDate = new Date();
if (myRealDate.typof('Date')) { /* do things */ }
alert( myDate.typof() ); //=> String
KooiInc