5) Canvas Lesson

Default Parameters in JavaScript Functions

15 min to complete · By Ian Currie

In this lesson, you'll learn about default parameters in JavaScript. Default parameters allow you to define an optional argument to a function which can be handy in many situations.

Increase Flexibility With JavaScript Default Parameters

Default parameters allow you to define an default value to initialize a parameter in a function:

function demo(x = 1, y = 2) {
	console.log(x, y);
}

There are many ways you can call this function:

// Without providing any arguments at all:
demo(); // 1, 2

// With only one argument:
demo(2); // 2, 2

// With both arguments:
demo(2, 3); // 2, 3

// Explicitly passing undefined:
demo(undefined, 3); // 1, 3

As you can see, the parameters x and y have default values that can be overwritten by passing in arguments.

If you pass in undefined as an argument, the default value will be used instead. This is why it's generally good practice to define default parameters at the end of the parameter list.

function demo(x, y = 1) {
	console.log(x, y);
}

Otherwise, it can be confusing to know which parameter is being overwritten. That said, it will work if you have default parameters at the beginning of the parameter list:

function demo(x = 1, y) {
	console.log(x, y);
}

demo(undefined, 3); // 1, 3

It just means that you have to pass in undefined to overwrite the default values. Which is usually not ideal.

Colorful illustration of a light bulb

Default parameters and most of what is in this lesson also apply to arrow functions and function expressions.

JavaScript Default Parameters before ES6

You may have already used an aspect of default parameters without realizing it. For example, if you were to define the demo() function without any default parameters, and call it without any arguments, the parameters would be undefined:

function demo(x, y) {
	console.log(x, y);
}

// Without providing any arguments at all:
demo(); // undefined, undefined

In this case, the parameters x and y are undefined because they were not provided. This is the default behavior of JavaScript which can be useful in some cases, but can lead to errors if not careful.

Before default parameters were introduced, you would have to check if the parameters were undefined and assign a default value if they were:

function demo(x, y) {
	if (x === undefined) {
		x = 1;
	}
	if (y === undefined) {
		y = 2;
	}
	console.log(x, y);
}
Colorful illustration of a light bulb

Similarly, if you call the function with too many arguments, the extra arguments are ignored in the demo function:

function demo(x, y) {
	console.log(x, y);
}

// With too many arguments:
demo(1, 2, 3); // 1, 2

As you can see, the third argument is ignored in the current version of the demo function. However, you can access all the arguments passed to a function using the arguments object:

function demo(x, y) {
	console.log(arguments);
}

// With too many arguments:
demo(1, 2, 3); // Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]

This object is an array-like object that contains all the arguments passed to the function. It's not available in arrow functions.

Using Default Parameters with Objects

You can also use default parameters with objects. For example, you can define a function that takes an array as an argument and uses default parameters to initialize the array:

function demo(arr = [1, 2, 3]) {
	console.log(arr);
}

demo(); // [1, 2, 3]
demo([4, 5, 6]); // [4, 5, 6]

You can also use default parameters with objects:

function demo(user = { name: 'Nomad' }) {
	console.log(user);
}

demo(); // {name: "Nomad"}
demo({ name: 'CodingNomad' }); // {name: "CodingNomad"}

As you can see, the default object is used if no argument is provided.

Unlike a language like Python, the default object is instantiated every time the function is called. This means that if you modify the object, the changes won't persist across function calls:

function demo(scores = [0]) {
	scores.push(100);
	console.log(scores);
}

demo(); // [100]
demo(); // [100] (not [100, 100])

As you can see, every time the function is called, the default array is instantiated and the value is [0] which is what you might intuitively expect. This is not so in some languages like Python, where the default object is instantiated only once which is the source of some confusion for people learning Python.

Using Named Parameters

Sometimes you want to be able to define a function which takes a lot of arguments, but you don't want to have to remember the order of the arguments. Or, you may forget which argument is which when you're looking at the function call:

drawRectangle(true, 'red', 10, 20, 2, null, 0, 0, 1);

Looking at this function, it's clear that it draws a rectangle, but it's not clear what each argument is for. To understand what each argument is for, you have to look at the function definition. Furthermore, if you want to change the function itself, you have to be careful not to break everywhere the function is called.

To make functions with many arguments more manageable, you can use something called named parameters. Some languages have built-in support for named parameters, like Python. In JavaScript, to approximate named parameters, you can use an object as an argument and use destructuring to extract the values:

function drawRectangle({
	visible,
	color,
	height,
	width,
	thickness,
	linkedTo,
	x,
	y,
	id
}) {
	console.log({ x, y, height, width });
}

drawRectangle({
	x: 0,
	y: 0,
	id: 1,
	visible: true,
	width: 20,
	thickness: 2,
	color: 'red',
	height: 10,
	linkedTo: null
}); // {x: 0, y: 0, height: 10, width: 20}

This function takes an object as an argument and uses destructuring to extract all the properties. This allows you to pass in the arguments in any order, giving you flexibility to change the function definition. It also makes it clear what each argument is for when you're looking at the function call.

Using Default Parameters with Named Parameters

You can also use default parameters with named parameter destructuring.

function drawRectangle({
	x,
	y,
	height,
	width,
	visible = true,
	color = 'black',
	thickness = 1,
	linkedTo = null,
	id = 0
}) {
	console.log({ x, y, height, width, visible, color });
}

drawRectangle({
	x: 0,
	y: 0,
	width: 20,
	height: 10
}); // {x: 0, y: 0, height: 10, width: 20, visible: true, color: "black"}

This function takes an object as an argument and uses destructuring to extract all the properties. It also uses default parameters to initialize the properties if they are not provided.

Following best practices, the default parameters are defined at the end of the parameter list. This makes it clear which parameters are optional.

You Can't Use Spread Syntax to Define Default Parameters

You can't use the spread syntax to define default parameters. For example, this will throw an error:

function demo(...arr = [1, 2, 3]) {
	console.log(arr);
}

demo(); // Uncaught SyntaxError: Rest parameter may not have a default initializer

To use the spread syntax with default parameters, you'd have to do it in the function body:

function demo(...arr) {
	arr = arr.length === 0 ? [1, 2, 3] : arr;
	console.log(arr);
}

demo(); // [1, 2, 3]
demo([4, 5, 6]); // [4, 5, 6]

// You can still use spreading in the function call:
const arr = [7, 8, 9];
demo(...arr); // [7, 8, 9]

Scope of Default Parameters

Default parameters are scoped to the function body. For example, you can't access the default parameters outside the function body:

function demo(x = 1, y = 2) {
	console.log(x, y);
}

console.log(x, y); // Uncaught ReferenceError: x is not defined

As you can see, no hoisting is done for default parameters.

Using Function Calls as Default Parameters

You can also use function calls as default parameters. For example, you can define a function that returns a random number and use it as a default parameter:

function getRandomNumber() {
	return Math.random();
}

function demo(x = getRandomNumber()) {
	console.log(x);
}

demo(); // 0.8998845271864933
demo(); // 0.5066114818813781

As you can see, the function is called every time the default parameter is used. This can be handy if you have a complex state object that you want to initialize as a default parameter, for example.

Summary: Default Parameters in JavaScript

You've expanded your understanding of JavaScript functions by exploring how default parameters work. You've:

  • Grasped how to set up default parameters in a function to give arguments optional default values.
  • Saw how when you pass undefined as an argument, the default value is utilized.
  • Noted the practice of placing default parameters at the end of the parameter list to reduce confusion over which arguments get default values.
  • Saw that before ES6, developers used conditional statements to assign default values within the function body.
  • Understood how to use object destructuring to emulate named parameters, making your code more readable and manageable, especially when dealing with multiple parameters.
  • Learned about other nuances such as default parameter scoping, using function calls as default parameters, and the inability to use the spread syntax to define default parameters.