Both answers correctly pointed out that the default (unassigned) variable in JavaScript is undefined , but none of the addresses are looking for what you seem to be looking for - the equivalent, for example. default statement in C #.
Fortunately, JavaScript has a very simple type system: everything that is not one of the six primitive types (five in ES5) is an object and can be called through its constructor. The next function given by a string representing
- primitive name JS;
- any valid production of a
typeof statement; or - the name of the function is either in the
this value that is called, or in its local scope
will result in a reasonable interpretation of the default value:
function defaultVal(type) { if (typeof type !== 'string') throw new TypeError('Type must be a string.'); // Handle simple types (primitives and plain function/object) switch (type) { case 'boolean' : return false; case 'function' : return function () {}; case 'null' : return null; case 'number' : return 0; case 'object' : return {}; case 'string' : return ""; case 'symbol' : return Symbol(); case 'undefined' : return void 0; } try { // Look for constructor in this or current scope var ctor = typeof this[type] === 'function' ? this[type] : eval(type); return new ctor; // Constructor not found, return new object } catch (e) { return {}; } }
You can call it like this:
defaultVal( typeof 1 ); // -> 0 defaultVal( 'number' ); // -> 0 defaultVal( 'object' ); // -> {} defaultVal( 'RegExp' ); // -> /(?:)/
Unfortunately, the JS typeof statement may be a little ... anameic for our purposes. For example, typeof null === 'object' and typeof [] === 'object' , which is probably not what you want.
To get around this, here is a function that returns the result of calling typeof by value if the result is not an “object”, in which case it will return 'null' if null and obj.constructor.name otherwise (with 'object' as a return value if all else fails):
function getType(obj) { var type = typeof obj; if (type !== 'object') return type; // primitive or function if (obj === null) return 'null'; // null // Everything else, check for a constructor var ctor = obj.constructor; var name = typeof ctor === 'function' && ctor.name; return typeof name === 'string' && name.length > 0 ? name : 'object'; }
And now we can have:
defaultVal( getType( 1234 ) ); // -> 0 defaultVal( getType( [99] ) ); // -> [] defaultVal( getType( 'ab' ) ); // -> "" defaultVal( getType( null ) ); // -> null (Not possible with typeof!) defaultVal( getType( /.*/ ) ); // -> /(?:)/ (Not possible with typeof!) function T () {} defaultVal( getType( new T ) ); // -> T {} (Not possible with typeof!)
I suspect this is so close to what you are looking for when you pack up. Also, to avoid any criticism: using the eval above may seem a little dirty, but this is the only way to get the named value from the current scope.
¹ This function cannot call a constructor created in another area; instead, I called using this , associated with an object containing any such constructors that it can reference:
function innerScopeCtor() { function T () {} return defaultVal.call( { T : T }, 'T' ); } innerScopeCtor();
If you do not, it will simply return to returning the new object.