views:

190

answers:

6

I'm currently in the creation of a javascript function library. Mainly for my own use, but you can never be sure if someone else ends up using it in their projects, I'm atleast creating it as if that could happen.
Most methods only work if the variables that are passed are of the correct datatype. Now my question is: What is the best way to alert users that the variable is not of the correct type? Should one throw an error like this?

function foo(thisShouldBeAString){ //just pretend that this is a method and not a global function
 if(typeof(thisShouldBeAString) === 'string') {
  throw('foo(var), var should be of type string');
 }
 #yadayada
}

I know that javascript does internal type conversion, but this can create very weird results (ie '234' + 5 = '2345' but '234' * 1 = 234) and this could make my methods do very weird things.

EDIT
To make things extra clear: I do not wish to do type conversion, the variables passed should be of the correct type. What is the best way to tell the user of my library that the passed variables are not of the correct type?

A: 

What's about just to silently convert string to numeric datatype on function startup?

You always can determine the datatype of 'string'. Can't you?

Thevs
I made my question more clear on the subject of type conversion.
Pim Jager
+1  A: 

Libraries like jQuery do not inform the user of the error.

If a function is expecting a number, and a user passes a string, the function just returns without doing anything.

That way, you will avoid JavaScript errors popping up on a live website.

PS. Just make sure to always type check your inputted parameters, to avoid JavaScript errors being thrown.

Andreas Grech
But wouldn't that also not inform the other developper that there is something bad going on, and the bad that is exactly going on?
Pim Jager
If you produce good documentation for your library, the developer will know that if a function expects a number for a parameter, and the developer passed in a string, the function won't work for that reason.
Andreas Grech
Actually I find it quite inconvenient, when I get an error telling me that somewhere deep inside some library something went wrong.
Rene Saarsoo
@Rene: I don't like your attitude ;) I'd vote for throwing errors - if someone fucked up somewhere, I want to know who and how to fix it. The problem is, errors don't really play well with JavaScript packers...
Christoph
So bassicly: do type checking and return false if var is not of correct type?
Pim Jager
+1  A: 

How about throw: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Statements/throw

Also type of does not distinguish between Array, Null, Object very well. Look at the funciton here: http://javascript.crockford.com/remedial.html, plus there are a few other ways to do it.

Personally I would not do the type checking since it is a step that will just add more processing time to the code. If you care about performance, you would want to chop off as many milliseconds of processing time as possible. Good Documentation will cure the need for the check.

epascarello
A: 

You could check for some value like "debug=1" set. If there is - you could output errors like alerts. So in development mode user will see them, but on real site he will turn it off. Same way browser will not show you error message - you need to look at JS console.

Also there is FireBug. You could detect that and put FB debug Messages also.

Malx
+3  A: 

The problem with type checking is that its actually quite hard to do. For example:-

var s = new String("Hello World!");
alert(typeof s);

What gets alerted? Ans: "object". Its true its a daft way to initialise a string but I see it quite often none-the-less. I prefer to attempt conversions where necessary or just do nothing.

Having said that in a Javascript environment in which I have total control (which is not true if you are simply providing a library) I use this set of prototype tweaks:-

String.prototype.isString = true;
Number.prototype.isNumber = true;
Boolean.prototype.isBoolean = true;
Date.prototype.isDate = true;
Array.prototype.isArray = true;

Hence testing for the common types can be as simple as:-

if (x.isString)

although you still need to watch out for null/undefined:-

if (x != null && x.isString)

In addition to avoiding the new String("thing") gotcha, this approach particularly comes into its own on Dates and Arrays.

AnthonyWJones
It's not necessary to extend the prototypes - check my answer below...
Christoph
Its understood that its not _necessary_ and in some cases its not even advisable however I find it clean and efficient.
AnthonyWJones
+1  A: 

Some small remarks on type checking - it's actually not that complicated:

Use typeof to check for primitives and instanceof to check for specific object types.

Example: Check for strings with

typeof x === 'string'

or

typeof x === 'string' || x instanceof String

if you want to include string objects.

To check for arrays, just use

x instanceof Array

This should work reasonably well (there are a few known exceptions - eg Firefox 3.0.5 has a bug where window instanceof Object === false although window.__proto__ instanceof Object === true).

edit: There are some further problems with detection of function objects:

In principle, you could both use typeof func === 'function' and func instanceof Function.

The catch is that in an unnamed browser from a big corporation these checks return the wrong results for some predefined functions (their type is given as 'object'). I know of no workaround for this - the checks only work reliably for user-defined functions...

edit2: There are also problems with objects passed from other windows/frames, as they will inherit from different global objects - ie instanceof will fail. Workarounds for built-in objects exists: For example, you can check for arrays via Object.prototype.toString.call(x) === '[object Array]'.

Christoph