Default value of a type in javascript
default-value, javascript, types
Solution
Both previous answers correctly note that the default (unassigned) value of a variable in JavaScript is `undefined`, but neither addresses what you seem to be looking for—an equivalent of e.g. the `default` operator in C#.
Fortunately, JavaScript has a very simple type system: everything that isn't one of the seven primitive types is an object and can be called via its constructor.¹ The following function, given a string representing
- the name of a JS primitive type, e.g.`'string'` or `'null'`;
- any valid production of the `typeof` operator, e.g. `'function'`;
- a function name either in the `this` value it is called with or its local scope²
will produce a reasonable interpretation of a "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 'bigint' : return BigInt(0);
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( 'bigint' ); // -> 0n
defaultVal( 'object' ); // -> {}
defaultVal( 'RegExp' ); // -> /(?:)/
Unfortunately, the JS `typeof` operator may be a bit… anameic for our purposes. For example, `typeof null === 'object'`¹, and `typeof [] === 'object'`, which probably isn't what you want.
To work around this, here's a function that returns the result of calling `typeof` on a value unless the result is 'object', in which case it will return `'null'` if the value is `null` and `obj.constructor.name` otherwise (with `'object'` as the fallback 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 as close to what you're looking for as you're going to get. Also, to head off any criticism: the use of eval above might seem a bit dirty, but it's the only way to get a named value from the current scope.
¹ `null` is a bit of an oddity. The ECMAScript 2020 specification clearly refers to it as a primitive; however, `typeof null` is `'object'` due to a bug in the original JavaScript implementation. At one point MDN excluded null from its list of primitives, counting only six primitives and stating that `null` should be considered a "special case for every `Object`".
Based on the spec, I refer to `null` as a primitive in this answer, and MDN has since been updated to agree with this stance.
² This function can't call a constructor instantiated in another scope; instead, I've made it possible to call it with `this` bound to an object containing any such constructors it may reference:
function innerScopeCtor() {
function T () {}
return defaultVal.call( { T : T }, 'T' );
}
innerScopeCtor(); // T {}
If you don't do this, it will just fall back to returning a new object.
Problem
Is there a function in JavaScript that returns the default value for a type name that is passed to it? For example: ``` var defaultValue = built_in_getDefaultValue("number"); console.log(defaultValue); // Logs the number 0 to the console. ```