Skip to content

Function Parameters

Understanding how JavaScript functions handle parameters (or arguments) is crucial for writing flexible and robust code. Modern JavaScript offers enhanced ways to work with parameters.

As you’ve learned, functions can be declared with parameters, which act as placeholders for values that will be passed to the function when it’s called.

function greet(name, greeting) {
// 'name' and 'greeting' are parameters
console.log(`${greeting}, ${name}!`);
}

Function parameters are the names listed in the function definition (e.g., name, greeting).

Function arguments are the actual values supplied to the function when it is invoked (e.g., greet('Alice', 'Hello'); ‘Alice’ and ‘Hello’ are arguments).

JavaScript is very flexible with function arguments:

  • JavaScript function definitions do not specify data types for parameters. You can pass any type of data.
  • JavaScript functions do not perform type checking on passed arguments by default. It’s up to the developer to validate types if necessary.
  • JavaScript functions do not strictly check the number of arguments received against the number of parameters declared.

Modern JavaScript (ES6 and later) allows you to specify default values for function parameters directly in the function signature. This is the preferred way to handle missing arguments.

If a function is called with fewer arguments than declared parameters, parameters without a corresponding argument are undefined. With default parameters, they take the specified default value instead.

function calculateArea(width, height = 10) {
// If height is not provided, it defaults to 10
return width * height;
}
console.log(calculateArea(5)); // Output: 50 (height defaults to 10)
console.log(calculateArea(5, 20)); // Output: 100 (height is 20)

Previously, you might have checked for undefined manually:

// Older way (less concise)
function myFunction(x, y) {
if (y === undefined) {
y = 0;
}
// ...
}

Default parameters make code cleaner and more readable.

Handling Excess Arguments & The arguments Object

Section titled “Handling Excess Arguments & The arguments Object”

If a function is called with more arguments than declared parameters, these extra arguments can be accessed.

1. The arguments Object (Traditional Functions):

Section titled “1. The arguments Object (Traditional Functions):”

Regular JavaScript functions (not arrow functions) have a built-in, array-like object called arguments.

The arguments object contains all arguments passed to the function, regardless of the number of parameters defined. It’s ‘array-like’ because it has a length property and indexed elements, but it’s not a true array (it doesn’t have methods like forEach, map, etc., without conversion).

function findMax() { // No parameters defined
let max = -Infinity;
for (let i = 0; i < arguments.length; i++) {
if (arguments[i] > max) {
max = arguments[i];
}
}
return max;
}
console.log(findMax(1, 123, 500, 115, 44, 88)); // Output: 500

ES6 introduced rest parameters, which provide a cleaner way to handle an indefinite number of arguments as a true array. This is generally preferred over the arguments object.

The rest parameter syntax uses three dots (...) followed by the name of the array that will hold the remaining arguments.

function sumAll(...numbers) {
// 'numbers' is a real array
let sum = 0;
for (const num of numbers) {
sum += num;
}
return sum;
// Or more concisely: return numbers.reduce((acc, current) => acc + current, 0);
}
console.log(sumAll(1, 123, 500, 115, 44, 88)); // Output: 871

A function can have named parameters before the rest parameter:

function multiply(multiplier, ...numbers) {
return numbers.map(n => n * multiplier);
}
console.log(multiply(2, 1, 2, 3)); // Output: [2, 4, 6]

Note: Rest parameters must be the last parameter in a function definition. Arrow functions do not have their own arguments object; use rest parameters instead.

Passing Arguments: By Value vs. By Reference (Sharing)

Section titled “Passing Arguments: By Value vs. By Reference (Sharing)”

Understanding how JavaScript passes arguments is key to avoiding unexpected behavior.

When you pass a primitive type (like a String, Number, Boolean, null, undefined, Symbol, BigInt) to a function, its value is copied. The function receives a copy of the value, not a reference to the original variable.

If the function modifies the parameter’s value, this change does not affect the original variable outside the function.

function changePrimitive(val) {
val = 100; // Modifies the local copy
console.log(`Inside function: ${val}`); // Output: Inside function: 100
}
let myNumber = 10;
changePrimitive(myNumber);
console.log(`Outside function: ${myNumber}`); // Output: Outside function: 10 (original is unchanged)

Objects Passed by Value of Reference (Pass by Sharing):

Section titled “Objects Passed by Value of Reference (Pass by Sharing):”

When you pass an object (including arrays and functions) as an argument, the value passed is actually a copy of the reference (memory address) to that object. This is often called “pass by sharing.”

This means the function parameter and the original variable point to the same object in memory.

If the function modifies a property of the object, this change is visible outside the function because both references point to the same underlying object.

function changeObjectProperty(obj) {
obj.name = "Updated Name"; // Modifies the property of the original object
}
let myPerson = { name: "Original Name" };
changeObjectProperty(myPerson);
console.log(myPerson.name); // Output: Updated Name

However, if the function reassigns the parameter to a completely new object, this does not affect the original variable outside the function. This is because you are changing the local reference copy, not the original object itself.

function reassignObject(obj) {
obj = { name: "New Object" }; // Reassigns the local reference
console.log(`Inside function (reassigned): ${obj.name}`); // Output: Inside function (reassigned): New Object
}
let anotherPerson = { name: "Initial Name" };
reassignObject(anotherPerson);
console.log(`Outside function: ${anotherPerson.name}`); // Output: Outside function: Initial Name (original is unchanged)

Understanding this distinction is crucial for predicting how functions interact with data.