I have a function like this one (simplified) :
doSmthg (name, age, callback) {
callback(name, age);
}
I'd like to have a default value for age if it's not provided.
I know I could do doSmthg(name, callback, age=42) {...}
in ES6 but I've been told callback should always be the last parameter as it make the call to the function more readable.
For now the solution I found is to do the following :
doSmthg (name, age, callback) {
if (arguments.length === 2) {
age = 42;
callback = age;
}
}
But I find this solution hard to read.
Is this the good solution ? Is there a better one ?
I have a function like this one (simplified) :
doSmthg (name, age, callback) {
callback(name, age);
}
I'd like to have a default value for age if it's not provided.
I know I could do doSmthg(name, callback, age=42) {...}
in ES6 but I've been told callback should always be the last parameter as it make the call to the function more readable.
For now the solution I found is to do the following :
doSmthg (name, age, callback) {
if (arguments.length === 2) {
age = 42;
callback = age;
}
}
But I find this solution hard to read.
Is this the good solution ? Is there a better one ?
Share Improve this question asked Nov 19, 2015 at 13:12 IggYIggY 3,1254 gold badges30 silver badges55 bronze badges 5 |3 Answers
Reset to default 10For this kind of situation you can use something like this:
function doSmthg(name, age, callback) {
if (typeof age === 'function') {
callback = age;
age = DEFAULT_VALUE;
}
//continue
}
Or you can use a Hash of options, that i think it's better because makes the code more readable, depending of the number of parameters:
function doSmthg(options, callback) {
var name = options.name;
var age = options.age || DEFAULT_VALUE;
//continue
}
doSmthg({ name: 'batman' }, function() {});
Also you can use the underscore #extend
function to merge the options with the default values.
If you have access to spread operator:
function foo(...args) {
const callback = args.pop();
const [name, age = 42] = args;
// ...
}
But I think it's time to use promises in NodeJS as well.
function foo(name, age = 42) {
return new Promise(resolve => {
setTimeout(() => resolve({name, age}), 1000);
});
}
//...
foo('Sándor').then(x => console.log(x)); // { name:"Sándor", age:42 }
Using ES6 promises you can get rid of the so called "callback pyramid", and makes it possible to use your function with ES7 async-await
keywords. The future is here!
Code
function foo(args, callback){
parsed = {name:"John Doe",age:12}; //default values
for(a in args) parsed[a] = args[a];
//Arguments are accessible like parsed.name
callback(parsed);
}
function callback(args){
alert(JSON.stringify(args));
}
foo({name:"Peter",extra:2},callback);//yields {"name":"Peter","age":12,"extra":2}
foo({name:"Mark",age:92},callback); //yields {"name":"Mark","age":92}
foo({},callback); //yields {"name":"John Doe","age":12}
Explanation
Depending on the number of arguments to pass it might look too verbose to your liking. The concept should be self explanatory but to put it in words, we group the arguments in an object and inside the function have an object with the default values (if needed). Then we override the defaults with those passed leaving us a very clear and clean callback
and verbose args.
Note that if extra parameters are passed, those are not lost in the process of setting the defaults.
doSmthg(name, age = 42)
(since you don't need to pass a callback anymore). – robertklep Commented Nov 19, 2015 at 13:30bluebird
because I have to promisify everything. – Dan Commented Nov 19, 2015 at 16:19