JavaScript Function Parameters

Beginner 6 min read

Function parameters define what inputs a function accepts. JavaScript offers powerful features like default values, rest parameters, and destructuring to make functions flexible and expressive.

Basic Parameters

Parameters are variables listed in the function definition. Arguments are the actual values passed when calling the function:

javascript
// Parameters vs Arguments
function add(a, b) {    // a, b are parameters
  return a + b;
}
add(2, 3);              // 2, 3 are arguments

// Missing arguments become undefined
function greet(name, greeting) {
  console.log(greeting + ", " + name);
}
greet("Alice");         // undefined, Alice

// Extra arguments are ignored
function first(a) {
  return a;
}
first(1, 2, 3);         // Returns 1, ignores 2 and 3
Note
JavaScript does not enforce the number of arguments. Missing arguments become undefined, extra arguments are ignored.

Default Parameters

Default parameters provide fallback values when arguments are not provided or are undefined:

javascript
// Default parameters (ES6)
function greet(name = "Guest") {
  return "Hello, " + name + "!";
}
greet();          // "Hello, Guest!"
greet("Alice");   // "Hello, Alice!"
greet(undefined); // "Hello, Guest!" (undefined triggers default)
greet(null);      // "Hello, null!" (null does NOT trigger default)

// Multiple defaults
function createUser(name = "Anonymous", role = "user", active = true) {
  return { name, role, active };
}
createUser();                    // { name: "Anonymous", role: "user", active: true }
createUser("Alice");             // { name: "Alice", role: "user", active: true }
createUser("Bob", "admin");      // { name: "Bob", role: "admin", active: true }

// Expressions as defaults
function getId(prefix = "id", num = Math.random()) {
  return prefix + "_" + num;
}
null vs undefined
Default parameters only trigger for undefined, not null. Passing null explicitly uses null as the value.

Rest Parameters

The rest parameter (...args) collects all remaining arguments into an array:

javascript
// Rest parameter collects remaining arguments
function sum(...numbers) {
  return numbers.reduce((acc, n) => acc + n, 0);
}
sum(1, 2);           // 3
sum(1, 2, 3, 4, 5);  // 15

// Rest must be last
function log(level, ...messages) {
  console.log("[" + level + "]", ...messages);
}
log("INFO", "Server", "started", "on port 3000");

// Rest creates a real array (unlike arguments)
function example(...args) {
  console.log(Array.isArray(args));  // true
  return args.map(x => x * 2);       // Array methods work
}

// Spread vs Rest
const nums = [1, 2, 3];
console.log(sum(...nums));  // Spread: expands array to arguments
Rest vs Spread
Rest (...args in parameters) collects into an array. Spread (...arr in function calls) expands an array into arguments.

Destructuring Parameters

Extract properties directly in the parameter list:

javascript
// Object destructuring in parameters
function printUser({ name, age }) {
  console.log(name + " is " + age);
}
printUser({ name: "Alice", age: 25 });

// With defaults
function configure({ host = "localhost", port = 3000 }) {
  console.log(host + ":" + port);
}
configure({ port: 8080 });  // "localhost:8080"

// Default for entire object (handles missing argument)
function init({ debug = false } = {}) {
  console.log("Debug mode:", debug);
}
init();          // Works! Uses {}
init({ debug: true });

// Array destructuring
function getFirstTwo([first, second]) {
  return { first, second };
}
getFirstTwo([1, 2, 3]);  // { first: 1, second: 2 }

// Renaming during destructure
function process({ name: userName, id: oderId }) {
  console.log(userName, oderId);
}

Try It Yourself

Experiment with different parameter patterns:

index.js
// Basic parameters
function greet(name, greeting) {
  return greeting + ", " + name + "!";
}
console.log(greet("Alice", "Hello"));

// Default parameters
function greetWithDefault(name = "Guest", greeting = "Hello") {
  return greeting + ", " + name + "!";
}
console.log(greetWithDefault());
console.log(greetWithDefault("Bob"));
console.log(greetWithDefault("Charlie", "Hi"));

// Rest parameters
function sum(...numbers) {
  return numbers.reduce((acc, n) => acc + n, 0);
}
console.log("Sum:", sum(1, 2, 3, 4, 5));

// Destructuring parameters
function printUser({ name, age, city = "Unknown" }) {
  console.log(name + " is " + age + " years old, from " + city);
}
printUser({ name: "Diana", age: 28, city: "NYC" });
printUser({ name: "Eve", age: 25 });

// Combining rest with regular params
function logFirst(first, ...rest) {
  console.log("First:", first);
  console.log("Rest:", rest);
}
logFirst("A", "B", "C", "D");

Try more advanced patterns:

index.js
// Default parameter expressions
function createId(prefix = "id", timestamp = Date.now()) {
  return prefix + "_" + timestamp;
}
console.log(createId());
console.log(createId("user"));

// Default using previous parameters
function greet(name, message = "Hello, " + name) {
  return message + "!";
}
console.log(greet("Alice"));
console.log(greet("Bob", "Hi there, Bob"));

// Destructuring with defaults
function configure({ host = "localhost", port = 3000, ssl = false } = {}) {
  console.log("Connecting to " + (ssl ? "https" : "http") + "://" + host + ":" + port);
}
configure({ port: 8080 });
configure({});
configure();  // Works because of = {} at the end

// Array destructuring in parameters
function getCoordinates([x, y, z = 0]) {
  return { x, y, z };
}
console.log(getCoordinates([10, 20]));
console.log(getCoordinates([1, 2, 3]));

// Nested destructuring
function processResponse({ data: { user, items }, status }) {
  console.log("Status:", status);
  console.log("User:", user);
  console.log("Items:", items.length);
}
processResponse({
  status: 200,
  data: { user: "Alice", items: [1, 2, 3] }
});

The Arguments Object (Legacy)

Before rest parameters, functions used the arguments object. It's still available but rest parameters are preferred:

javascript
// The arguments object (legacy, avoid in new code)
function oldSum() {
  let total = 0;
  for (let i = 0; i < arguments.length; i++) {
    total += arguments[i];
  }
  return total;
}
oldSum(1, 2, 3, 4);  // 10

// arguments is array-like, not a real array
function example() {
  console.log(arguments.length);     // Works
  // arguments.map(x => x);          // Error! No array methods

  // Convert to real array
  const args = Array.from(arguments);
  // or: const args = [...arguments];
}

// Arrow functions do NOT have arguments
const arrowFunc = () => {
  // console.log(arguments);  // Error!
};

// Use rest parameters instead (modern approach)
const modernSum = (...args) => args.reduce((a, b) => a + b, 0);
Avoid arguments
The arguments object is not available in arrow functions and is not a real array. Use rest parameters (...args) instead.

Best Practices

1. Use Default Parameters
Provide sensible defaults to make functions easier to use and avoid undefined checks inside the function.
2. Use Object Parameters for Many Options
When a function has many optional parameters, use an options object with destructuring instead of positional arguments.
3. Use Rest Instead of arguments
Rest parameters create real arrays and work with arrow functions. Avoid the legacy arguments object.
4. Limit Parameter Count
Functions with more than 3-4 parameters are hard to use. Consider using an options object instead.

Test Your Knowledge

Test Your Knowledge

5 questions
Question 1

Where must the rest parameter (...args) be placed?

Question 2

What is the value of x in: function f(x = 5) {} called as f(undefined)?

Question 3

What does the arguments object contain?

Question 4

Can default parameters reference earlier parameters?

Question 5

What happens if you pass null to a parameter with a default value?

Practice Exercise

Object Merge Function
Easy

Create a function that merges multiple objects using rest parameters and spread operator.

Starter Code
// Challenge: Create a function that merges multiple objects
// Later objects should override earlier ones
// merge({ a: 1 }, { b: 2 }, { a: 3 }) => { a: 3, b: 2 }

function merge(...objects) {
  // TODO: Merge all objects into one
  // Use reduce and spread operator
}

// Test cases
console.log(merge({ a: 1 }, { b: 2 }));
// Should print { a: 1, b: 2 }

console.log(merge({ a: 1 }, { a: 2, b: 3 }, { c: 4 }));
// Should print { a: 2, b: 3, c: 4 }

console.log(merge({ x: 1 }));
// Should print { x: 1 }

console.log(merge());
// Should print {}

Frequently Asked Questions

Can I skip middle parameters?

Not directly with positional parameters. Pass undefined to trigger the default: func(1, undefined, 3). For cleaner code, use an options object instead.

What happens if I pass too many arguments?

Extra arguments are ignored unless you use rest parameters to capture them. They are still accessible via the arguments object in regular functions.

Can default parameters have side effects?

Yes, default parameter expressions are evaluated each time the function is called (when needed). This means Date.now() as a default gives a fresh timestamp each call.

Summary

JavaScript function parameters offer many features:

  • Default parameters: function f(x = 10) {}
  • Rest parameters: function f(...args) {}
  • Destructuring: function f({ name, age }) {}

Key points:

  • Default values only apply for undefined, not null
  • Rest parameters must be last and create a real array
  • Use object destructuring for functions with many options
  • Avoid the legacy arguments object