Set a default parameter value for a JavaScript function
Solution 1
From ES6/ES2015, default parameters are in the language specification.
function read_file(file, delete_after = false) {
// Code
}
just works.
Reference: Default Parameters - MDN
Default function parameters allow formal parameters to be initialized with default values if no value or undefined is passed.
You can also simulate default named parameters via destructuring:
// the `= {}` below lets you call the function without any parameters
function myFor({ start = 5, end = 1, step = -1 } = {}) { // (A)
// Use the variables `start`, `end` and `step` here
···
}
Pre ES2015,
There are a lot of ways, but this is my preferred method — it lets you pass in anything you want, including false or null. (typeof null == "object"
)
function foo(a, b) {
a = typeof a !== 'undefined' ? a : 42;
b = typeof b !== 'undefined' ? b : 'default_b';
...
}
Solution 2
function read_file(file, delete_after) {
delete_after = delete_after || "my default here";
//rest of code
}
This assigns to delete_after
the value of delete_after
if it is not a falsey value otherwise it assigns the string "my default here"
. For more detail, check out Doug Crockford's survey of the language and check out the section on Operators.
This approach does not work if you want to pass in a falsey value i.e. false
, null
, undefined
, 0
or ""
. If you require falsey values to be passed in you would need to use the method in Tom Ritter's answer.
When dealing with a number of parameters to a function, it is often useful to allow the consumer to pass the parameter arguments in an object and then merge these values with an object that contains the default values for the function
function read_file(values) {
values = merge({
delete_after : "my default here"
}, values || {});
// rest of code
}
// simple implementation based on $.extend() from jQuery
function merge() {
var obj, name, copy,
target = arguments[0] || {},
i = 1,
length = arguments.length;
for (; i < length; i++) {
if ((obj = arguments[i]) != null) {
for (name in obj) {
copy = obj[name];
if (target === copy) {
continue;
}
else if (copy !== undefined) {
target[name] = copy;
}
}
}
}
return target;
};
to use
// will use the default delete_after value
read_file({ file: "my file" });
// will override default delete_after value
read_file({ file: "my file", delete_after: "my value" });
Solution 3
I find something simple like this to be much more concise and readable personally.
function pick(arg, def) {
return (typeof arg == 'undefined' ? def : arg);
}
function myFunc(x) {
x = pick(x, 'my default');
}
Solution 4
In ECMAScript 6 you will actually be able to write exactly what you have:
function read_file(file, delete_after = false) {
// Code
}
This will set delete_after
to false
if it s not present or undefined
. You can use ES6 features like this one today with transpilers such as Babel.
See the MDN article for more information.
Solution 5
Default Parameter Values
With ES6, you can do perhaps one of the most common idioms in JavaScript
relates to setting a default value for a function parameter. The way we’ve done this for years should look quite familiar:
function foo(x,y) {
x = x || 11;
y = y || 31;
console.log( x + y );
}
foo(); // 42
foo( 5, 6 ); // 11
foo( 5 ); // 36
foo( null, 6 ); // 17
This pattern is most used, but is dangerous when we pass values like
foo(0, 42)
foo( 0, 42 ); // 53 <-- Oops, not 42
Why? Because the 0 is falsy
, and so the x || 11 results in 11
, not the directly passed in 0. To fix this gotcha, some people will instead write the check more verbosely like this:
function foo(x,y) {
x = (x !== undefined) ? x : 11;
y = (y !== undefined) ? y : 31;
console.log( x + y );
}
foo( 0, 42 ); // 42
foo( undefined, 6 ); // 17
we can now examine a nice helpful syntax added as of ES6
to streamline the assignment of default values to missing arguments:
function foo(x = 11, y = 31) {
console.log( x + y );
}
foo(); // 42
foo( 5, 6 ); // 11
foo( 0, 42 ); // 42
foo( 5 ); // 36
foo( 5, undefined ); // 36 <-- `undefined` is missing
foo( 5, null ); // 5 <-- null coerces to `0`
foo( undefined, 6 ); // 17 <-- `undefined` is missing
foo( null, 6 ); // 6 <-- null coerces to `0`
x = 11
in a function declaration is more like x !== undefined ? x : 11
than the much more common idiom x || 11
Default Value Expressions
Function
default values can be more than just simple values like 31; they can be any valid expression, even a function call
:
function bar(val) {
console.log( "bar called!" );
return y + val;
}
function foo(x = y + 3, z = bar( x )) {
console.log( x, z );
}
var y = 5;
foo(); // "bar called"
// 8 13
foo( 10 ); // "bar called"
// 10 15
y = 6;
foo( undefined, 10 ); // 9 10
As you can see, the default value expressions are lazily evaluated, meaning they’re only run if and when they’re needed — that is, when a parameter’s argument is omitted or is undefined.
A default value expression can even be an inline function expression call — commonly referred to as an Immediately Invoked Function Expression (IIFE)
:
function foo( x =
(function(v){ return v + 11; })( 31 )
) {
console.log( x );
}
foo(); // 42
Comments
-
Tilendor almost 3 years
I would like a JavaScript function to have optional arguments which I set a default on, which get used if the value isn't defined (and ignored if the value is passed). In Ruby you can do it like this:
def read_file(file, delete_after = false) # code end
Does this work in JavaScript?
function read_file(file, delete_after = false) { // Code }
-
Adam about 15 yearsI find this insufficient, because I may want to pass in false.
-
Russ Cam about 15 yearsI find it's adequate for most situations
-
Camilo Martin almost 12 yearsYou can also encapsulate it as such:
function defaultFor(arg, val) { return typeof arg !== 'undefined' ? arg : val; }
and then you can call it asa = defaultFor(a, 42);
-
Triang3l over 11 yearsThis is too slow, use
a = ((a != null) ? a : 42);
. -
jinglesthula over 11 yearsBecause it doesn't work for falsey values, it may create a maintenance nightmare. A bit of code that has always been passed truthy values before and suddenly fails because a falsey one is passed in should probably be avoided where a more robust approach is available.
-
Sampo Sarrala - codidact.org over 11 years@SiPlus then it is not anymore default value and there's no point other than quickly changing a lot of values passed to functions (like using defined constants in place of
null
). Basically your code translatesnull
to42
. Ifa
isundefined
in your example then it will stayundefined
and it is not getting any default value. -
Triang3l over 11 years@Sampo
undefined==null
(but not===null
). But if you intentionally passnull
to the function, my code will not work. -
Sampo Sarrala - codidact.org over 11 years@SiPlus and you got extra reference errors for free of charge while trying to use
undefined
objects :p Even while it may work with some browsers and might be faster,null
is still an object andundefined
is reference to primitive type that is trying to tell that there is nothing here, not evennull
. See here, both cases in nutshell: JavaScript/Reference/Global_Objects/undefined. -
Ayush over 11 yearsHow come, in this case,
delete_after
doesn't get the boolean result of the expressiondelete_after || "my default value"
? -
Russ Cam over 11 years@xbonez it assigns to
delete_after
the value ofdelete_after
if it is not a falsey value otherwise it assigns the stringmy default here
. For more detail, check out Doug Crockford's survey of the lanugage and check out the section on Operators - javascript.crockford.com/survey.html -
Dziamid about 11 yearsif you check against the property of an object, then
typeof
is redundant.function foo(data) { var bar = data.bar !== undefined ? data.bar : 'default'; }
This won't throw reference errors and is concise. -
Rick Eyre almost 11 yearsThis didn't work for me. If you pass in no value you can't use typeof on the parameter. You have to instead use
var === undefined
-
Muhammad Raihan Muhaimin over 10 yearsHere is the catch : "This approach does not work if you want to pass in a falsey value i.e. false, null, undefined, 0 or "". If you require falsey values to be passed in you would need to use the method in Tom Ritter's answer." Thanks for clarifying.
-
andersand almost 10 yearsUpdate: If you're using underscore.js already I find it even better to use
_.defaults(iceCream, {flavor: "vanilla", sprinkles: "lots"});
. Using the global namespace as shown in this answer is by many considered a bad practice. You may also consider rolling your own utility for this common task (eg.util.default(arg, "defaul value")
) if don't want to use underscore, but I mostly end up using underscore sooner or later anyway no point in reinventing the wheel. -
JasonDavis over 9 years@andersand I like the idea of something like
util.default(arg, "defaul value"))
would you or @tj111 mind posting a quick demo? -
Daddy32 over 9 yearsI know it's really minor, but I don't like how you are assigning
a = a
andb = b
when those parameters are not undefined. Also, that ternary operator with a bit complicated condition may be hard to read for future maintainers. I would prefer following syntax:if (typeof a == 'undefined') a = 42
- no unnecessary assignment plus a little bit easier to read. -
Admin about 9 yearsI actually recommend this one, i use it and call it "por" which stands for "parameter or"
-
Abe Voelker about 9 yearsIs there any reason to use
typeof
? It would seem simpler to just doa === undefined
. Plus that way you'd get a reference error if you misspelledundefined
vs. putting it in a string. -
Riveascore about 9 yearsAnd we don't have to worry about
a
ending up as a global variable if it wasn't specified in the function call? -
Adriano Resende almost 9 yearsWaiting for browser any get ECMAScript 6
-
harryg almost 9 yearsWhat would Babel transpile this to?
-
Felix Kling almost 9 years@harryg: babeljs.io/repl/…
-
freemanoid almost 9 yearsHere is the compatibility table for ES6 kangax.github.io/compat-table/es6/#default_function_parameters Unfortunately this syntax isn't supported yet.
-
Paul almost 9 yearsIt may not work if you need falsey values but my functions will frequently take an optional options object. This is perfect for that use case:
opts = opts || {}
. -
Sebi almost 9 years@AbeVoelker There were some problems with
undefined
not being a keyword in older javascript engines - so you could overwrite it. You can always generate an undefined by usingvoid
- for example:a = a !== void 0 ? a : "Default";
- it is ugly, and there is something fundamentally wrong with the code overwriting undefined anyway. -
Sebi almost 9 years@Sebi Also that's how it roughly looks when you compile/preprocess TypeScript function with parameters having a default value.
-
OsamaBinLogin over 8 yearsDon't say typeof arg == 'undefined', instead say arg === undefined
-
beerwin over 8 yearsThis may be better this way:
delete_after = typeof(delete_after) != 'undefined' ? delete_after : "my default here";
-
user over 8 yearsThis answer is not useful because it is a duplicate
-
Alnitak over 8 years@OsamaBinLogin what you say is correct for current JS - the older test persists because on some browsers it used to be possible to overwrite
undefined
with some other value, causing the test to fail. -
cregox over 8 yearswhy not simply using the less cryptic
if (typeof a === 'undefined') a = 42;
? -
Dmitri Pavlutin over 8 yearsWhat happens if
delete_after
is0
ornull
? It will not work correct for these cases. -
Diptox over 8 yearsyou can use
a = a || 42;
it's more easy -
Mark Brackett over 8 yearsor, you could just default to a falsey value - which is generally a good default anyway (eg., false for bools, empty string for strings, 0 for numbers, etc.) - in which case it doesn't really matter what was passed in.
-
ArtOfWarfare about 8 yearsEdge14 and and current Chrome and Opera support it now, along with FF from last year... now just waiting on Safari, which supports it in the current beta, so hopefully in ~4 months the latest versions of all browsers will support it. Then you'll just have to wait for your users to actually update their browsers (or push them to do so.)
-
DiMono almost 8 yearsAssignment within the function definition also doesn't work in IE 11, which is the most current version of IE for Windows 8.1.
-
Wes almost 8 yearsFYI: MS Edge and IE11 throw an error when assigning a default value like so: function badArg(imOK, imNOT='') {} - it will balk at the ='' - didn't test null, just removed it because it wasn't actually necessary.
-
bevanb almost 8 yearsNote that setting defaults in the parameter declaration doesn't currently work in mobile Safari or Chrome.
-
gcampbell almost 8 yearsIn case anyone's wondering,
function myfunc(a,b=10)
is ES6 syntax, there are links to compatibility tables in other answers. -
Sarath S Nair over 7 yearsYou can simply write function foo(a, b) { a = a || 42; b = b || 'default_b'; ... }
-
Rutrus over 7 years@StephanBijzitter it only would be true in some cases. But if you only want the default values to unset values this didn't work, because 0 or null !=== false.
-
Stephan Bijzitter over 7 years@Rutrus: I don't understand anything you just said.
-
aashah7 about 7 yearsWhat about
delete_after = delete_after === undefined ? false : delete_after
? -
Gert van den Berg about 7 yearsIt is not currently portable... IE... developer.mozilla.org/en/docs/Web/JavaScript/Reference/… (And it is a duplicate answer...)
-
Mr. Lance E Sloan about 7 years@jinglesthula suggests this approach may create a maintenance nightmare. I'd say it more strongly: It most likely WILL be a nightmare. Russ Cam wrote that this approach won't work when values that can be cast to Boolean false are used. If you use this approach, how can you be sure that your code won't be called with a false value? You can't. Therefore, this approach isn't a good idea. The only current safe approach is to use
typeof
and compare the results with'undefined'
. -
Mr. Lance E Sloan about 7 years@Alnitak: It's still possible to override
undefined
. So, it's still a good idea to usetypeof
and'undefined'
. -
jinglesthula about 7 yearsThankfully we now have ES6 (and Babel), so this will be more of a moot point going forward now that the language natively supports this in a sane fashion. For those not on ES6 yet, I think saying "if you require falsey values" or "if you want to pass in a falsey value" is a bit misleading, since you may be passed falsey values you didn't anticipate when writing the code, either because what you write will be used by other people, or by your future self (which is practically the same as "other people") that forgot a li'l caveat baked into old code.
-
Alnitak about 7 years@LS It's no longer possible to create a global variable named
undefined
. It's only possible to create a local variable or function parameter of that name, and if you introduce one of those into your function's lexical scope you've only got yourself to blame. -
Guillaume Vincent about 7 yearsIs there a reason why you don't use a positive if?
a = typeof a === 'undefined' ? 42 : a;
I mean===
instead of!==
? -
Doug Coburn over 6 yearsI suggest updating your answer to warn about the gotchas with using default parameter values. See my post below: stackoverflow.com/questions/894860/…
-
KayakinKoder over 6 yearsAccording to this, default parameters are now supported by most browsers (including mobile), IE being the exception: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… and kangax.github.io/compat-table/es6
-
Vojtech Ruzicka over 6 yearsAlso, for a junior unaware of the concept this will look really cryptic and confusing. Checking for undefined in a IF and then assigning a value is not that longer and it is much more intent revealing. You can immediately see what is it for even as a complete newbie.
-
Tanya Gupta over 6 yearsYou can also use default value assignment with the destructuring assignment notation
-
Sumesh TG almost 6 yearsThis works for variebles as well as objects. Thank you.
-
Serg over 5 yearsThe first example is not universal because that won't work for the case with a method like
setValue(v)
if you pass0
wherev
should be1
by default. It will work with strings and objects only. -
instead over 5 yearsThis "better solution" is quite unreadable. I would rather recommend to check variable type like
typeof deleteAfter === 'bool'
and throw Exception otherwise. Plus in case of using methods like map/foreach etc. just use them with caution and wrap called functions with anonymous function.['1', '2', '3'].map((value) => {read_file(value);})
-
Doug Coburn over 5 yearsThat's a good point. I was trying to avoid using libraries in my code snippet, but this idiom is quite messy in pure javascript. Personally, I would use lodash's
get
method to retrieve deleteAfter. Throwing an exception iftypeof 'deleteAfter' !== 'bool'
may also be a good prudent measure. I don't like designing methods that require the caller to "use caution". Caution is the responsibility of the function, not the caller. The end behavior should follow the principle of least surprise. -
instead over 5 yearsI agree, that method shouldn't be wrote the way, that calling it, can broke its behavior. But keep in mind that function is like model, and caller is like controller. Model should take care of data processing. Function (method) should expect that data, can be passed wrong way and handle it. That's why checking type of parameter plus throwing Exception, is the best way. Even though it's more complex. But still it can save You from scratching Your head and keep asking... WHY IT IS NOT WORKING?! and then... WHY IT IS WORKING?!
-
Taco タコス over 4 years+1 This particular Q&A is a perfect example of the fact that the majority of developers will come to SO before anywhere else. :)