Parameters and arguments are how you pass data into functions. Modern JavaScript offers powerful features like default parameters, rest parameters, and destructuring that make functions more flexible and easier to use. Let's master these essential concepts for writing robust, versatile functions!
Parameters vs Arguments
While often used interchangeably, parameters and arguments are technically different:
- Parameters: Variables listed in the function definition
- Arguments: Actual values passed when calling the function
// Parameters: a and b (defined in function)
function add(a, b) {
return a + b;
}
// Arguments: 5 and 3 (passed when calling)
let result = add(5, 3);
console.log(result); // 8
// Another way to think about it:
function greet(name, age) { // name, age are PARAMETERS
return `Hello ${name}, you are ${age} years old`;
}
greet("Alice", 25); // "Alice", 25 are ARGUMENTSHow Arguments Map to Parameters
function introduce(name, age, city) {
console.log(`Name: ${name}`);
console.log(`Age: ${age}`);
console.log(`City: ${city}`);
}
// Arguments map to parameters in order
introduce("Alice", 25, "NYC");
// name = "Alice"
// age = 25
// city = "NYC"
// Output:
// Name: Alice
// Age: 25
// City: NYCBasic Parameters
Single Parameter
function double(num) {
return num * 2;
}
console.log(double(5)); // 10
console.log(double(10)); // 20
// Single parameter functions are common
function capitalize(text) {
return text.charAt(0).toUpperCase() + text.slice(1);
}
console.log(capitalize("hello")); // "Hello"Multiple Parameters
function calculateArea(width, height) {
return width * height;
}
console.log(calculateArea(5, 10)); // 50
function createUser(name, email, age) {
return {
name: name,
email: email,
age: age,
createdAt: new Date()
};
}
console.log(createUser("Alice", "alice@test.com", 25));What Happens with Mismatched Arguments
function greet(firstName, lastName) {
console.log(`Hello ${firstName} ${lastName}`);
}
// Too few arguments - missing parameter becomes undefined
greet("Alice");
// Output: "Hello Alice undefined"
// Too many arguments - extra arguments ignored
greet("Alice", "Smith", "Extra", "Values");
// Output: "Hello Alice Smith"
// (Extra arguments "Extra" and "Values" are ignored)
// No arguments at all
greet();
// Output: "Hello undefined undefined"Important: JavaScript doesn't throw errors for mismatched argument counts. Missing arguments become undefined, and extra arguments are ignored (but accessible via arguments object or rest parameters).
Default Parameters
Default parameters allow you to specify default values for parameters if no argument is passed (or if undefined is passed).
Basic Default Parameters
// Without defaults (old way)
function greet(name) {
name = name || "Guest"; // Fallback to "Guest"
return `Hello, ${name}!`;
}
// With defaults (modern way)
function greetModern(name = "Guest") {
return `Hello, ${name}!`;
}
console.log(greetModern()); // "Hello, Guest!"
console.log(greetModern("Alice")); // "Hello, Alice!"
// Multiple default parameters
function createUser(name = "Anonymous", role = "User", active = true) {
return { name, role, active };
}
console.log(createUser());
// { name: "Anonymous", role: "User", active: true }
console.log(createUser("Alice", "Admin"));
// { name: "Alice", role: "Admin", active: true }Default Parameters with Different Types
// String default
function greet(message = "Hello, World!") {
console.log(message);
}
// Number default
function multiply(a, b = 1) {
return a * b;
}
console.log(multiply(5)); // 5 (5 * 1)
console.log(multiply(5, 3)); // 15
// Boolean default
function setOptions(verbose = false, debug = false) {
console.log(`Verbose: ${verbose}, Debug: ${debug}`);
}
setOptions(); // Verbose: false, Debug: false
setOptions(true); // Verbose: true, Debug: false
setOptions(true, true); // Verbose: true, Debug: true
// Array default
function processItems(items = []) {
console.log(`Processing ${items.length} items`);
}
processItems(); // "Processing 0 items"
processItems([1, 2, 3]); // "Processing 3 items"
// Object default
function configure(options = {}) {
let theme = options.theme || "light";
let fontSize = options.fontSize || 16;
console.log(`Theme: ${theme}, Size: ${fontSize}`);
}
configure(); // Theme: light, Size: 16
configure({ theme: "dark" }); // Theme: dark, Size: 16
configure({ theme: "dark", fontSize: 18 }); // Theme: dark, Size: 18Default Parameters with Expressions
// Expression as default
function greet(name = "User", time = new Date().getHours()) {
let greeting = time < 12 ? "Good morning" : "Good afternoon";
return `${greeting}, ${name}!`;
}
console.log(greet()); // Uses current hour
// Function call as default
function getDefaultName() {
return "Guest_" + Math.floor(Math.random() * 1000);
}
function createUser(name = getDefaultName()) {
return { name, id: Date.now() };
}
console.log(createUser()); // Random guest name
console.log(createUser("Alice")); // "Alice"
// Previous parameter as default
function calculatePrice(price, tax = price * 0.08) {
return price + tax;
}
console.log(calculatePrice(100)); // 108 (100 + 8)
console.log(calculatePrice(100, 10)); // 110 (100 + 10)Undefined vs Null
function greet(name = "Guest") {
return `Hello, ${name}!`;
}
// undefined triggers default
console.log(greet(undefined)); // "Hello, Guest!"
// null does NOT trigger default
console.log(greet(null)); // "Hello, null!"
// Only undefined (or no argument) uses default
console.log(greet()); // "Hello, Guest!"
console.log(greet("Alice")); // "Hello, Alice!"Rest Parameters
The rest parameter (...paramName) collects all remaining arguments into an array. It must be the last parameter.
Basic Rest Parameter
// Collect all arguments into array
function sum(...numbers) {
let total = 0;
for (let num of numbers) {
total += num;
}
return total;
}
console.log(sum(1, 2, 3)); // 6
console.log(sum(1, 2, 3, 4, 5)); // 15
console.log(sum(10, 20, 30, 40, 50, 60)); // 210
// Rest parameter is a real array
function logArguments(...args) {
console.log("Type:", typeof args); // "object"
console.log("Is Array:", Array.isArray(args)); // true
console.log("Length:", args.length);
console.log("Args:", args);
}
logArguments(1, 2, 3, 4, 5);Rest Parameters with Named Parameters
// First parameter named, rest collected
function greetAll(greeting, ...names) {
return names.map(name => `${greeting}, ${name}!`);
}
console.log(greetAll("Hello", "Alice", "Bob", "Charlie"));
// ["Hello, Alice!", "Hello, Bob!", "Hello, Charlie!"]
// Multiple named parameters, then rest
function createTeam(teamName, captain, ...members) {
return {
name: teamName,
captain: captain,
members: members,
size: members.length + 1
};
}
console.log(createTeam("Warriors", "Alice", "Bob", "Charlie", "Diana"));
// {
// name: "Warriors",
// captain: "Alice",
// members: ["Bob", "Charlie", "Diana"],
// size: 4
// }Rest Parameter Patterns
// Find maximum
function max(...numbers) {
return Math.max(...numbers);
}
console.log(max(5, 10, 3, 8, 15)); // 15
// Concatenate strings
function concatenate(separator, ...strings) {
return strings.join(separator);
}
console.log(concatenate(" - ", "Apple", "Banana", "Orange"));
// "Apple - Banana - Orange"
// Filter and sum
function sumEven(...numbers) {
return numbers
.filter(n => n % 2 === 0)
.reduce((sum, n) => sum + n, 0);
}
console.log(sumEven(1, 2, 3, 4, 5, 6, 7, 8)); // 20
// Collect and process
function logWithTimestamp(message, ...details) {
console.log(`[${new Date().toISOString()}] ${message}`);
if (details.length > 0) {
console.log("Details:", details);
}
}
logWithTimestamp("User login", "userId: 123", "IP: 192.168.1.1");Note: Rest parameter must be the LAST parameter. You can't have parameters after a rest parameter: function bad(...rest, last) {} ❌
The Arguments Object
Regular functions (not arrow functions) have an arguments object that contains all passed arguments.
Using Arguments Object
// Regular function has 'arguments' object
function showArguments() {
console.log("Type:", typeof arguments); // "object"
console.log("Length:", arguments.length);
console.log("Arguments:", arguments);
// Access by index
console.log("First:", arguments[0]);
console.log("Second:", arguments[1]);
}
showArguments(10, 20, 30, 40);
// Type: object
// Length: 4
// Arguments: [10, 20, 30, 40]
// First: 10
// Second: 20
// Sum all arguments (old way)
function sum() {
let total = 0;
for (let i = 0; i < arguments.length; i++) {
total += arguments[i];
}
return total;
}
console.log(sum(1, 2, 3, 4, 5)); // 15Arguments Object Limitations
function testArguments() {
// arguments is array-LIKE, not a real array
console.log(Array.isArray(arguments)); // false
// Doesn't have array methods
// arguments.map(x => x * 2); // Error! map is not a function
// Convert to real array (old way)
let argsArray = Array.prototype.slice.call(arguments);
console.log(Array.isArray(argsArray)); // true
// Modern way: Array.from() or spread
let argsArray1 = Array.from(arguments);
let argsArray2 = [...arguments];
// Now you can use array methods
let doubled = argsArray2.map(x => x * 2);
console.log(doubled);
}
testArguments(1, 2, 3, 4);Rest Parameters vs Arguments Object
Modern approach is cleaner
Arguments Object
// Using arguments object (old way)
function sum() {
let total = 0;
for (let i = 0; i < arguments.length; i++) {
total += arguments[i];
}
return total;
}
// Must convert to array for methods
function double() {
return [...arguments].map(x => x * 2);
}
// Doesn't work in arrow functions
const sumArrow = () => {
// return arguments[0]; // Error!
};Rest Parameters (Preferred)
// Using rest parameters (modern)
function sum(...numbers) {
let total = 0;
for (let num of numbers) {
total += num;
}
return total;
}
// Already an array!
function double(...numbers) {
return numbers.map(x => x * 2);
}
// Works everywhere
const sumArrow = (...numbers) => {
return numbers.reduce((a, b) => a + b, 0);
};Best Practice: Use rest parameters instead of the arguments object. Rest parameters are a real array, work with arrow functions, and have clearer intent.
Destructuring Parameters
You can destructure objects and arrays directly in function parameters for cleaner code.
Object Destructuring in Parameters
// Without destructuring
function createUser(user) {
return `${user.name} is ${user.age} years old from ${user.city}`;
}
// With destructuring
function createUserBetter({ name, age, city }) {
return `${name} is ${age} years old from ${city}`;
}
let user = { name: "Alice", age: 25, city: "NYC" };
console.log(createUserBetter(user));
// "Alice is 25 years old from NYC"
// With default values
function greetUser({ name = "Guest", title = "User" }) {
return `Hello, ${title} ${name}!`;
}
console.log(greetUser({ name: "Alice", title: "Dr." }));
// "Hello, Dr. Alice!"
console.log(greetUser({ name: "Bob" }));
// "Hello, User Bob!"
console.log(greetUser({}));
// "Hello, User Guest!"Array Destructuring in Parameters
// Array destructuring
function getFullName([firstName, lastName]) {
return `${firstName} ${lastName}`;
}
console.log(getFullName(["Alice", "Smith"])); // "Alice Smith"
// With rest parameter
function logCoordinates([x, y, ...rest]) {
console.log(`X: ${x}, Y: ${y}`);
if (rest.length > 0) {
console.log("Additional coordinates:", rest);
}
}
logCoordinates([10, 20]); // X: 10, Y: 20
logCoordinates([10, 20, 30, 40]); // X: 10, Y: 20, Additional: [30, 40]Nested Destructuring
// Nested object destructuring
function displayUser({ name, address: { city, country } }) {
return `${name} lives in ${city}, ${country}`;
}
let user = {
name: "Alice",
address: {
city: "NYC",
country: "USA",
zip: "10001"
}
};
console.log(displayUser(user));
// "Alice lives in NYC, USA"
// With defaults for nested properties
function getLocation({
address: {
city = "Unknown",
country = "Unknown"
} = {}
} = {}) {
return `${city}, ${country}`;
}
console.log(getLocation(user)); // "NYC, USA"
console.log(getLocation({})); // "Unknown, Unknown"
console.log(getLocation()); // "Unknown, Unknown"Practical Destructuring Patterns
// API options pattern
function fetchData(url, {
method = "GET",
headers = {},
timeout = 5000
} = {}) {
console.log(`Fetching ${url}`);
console.log(`Method: ${method}`);
console.log(`Timeout: ${timeout}ms`);
// Fetch implementation...
}
fetchData("https://api.example.com/users");
// Uses all defaults
fetchData("https://api.example.com/users", {
method: "POST",
headers: { "Content-Type": "application/json" }
});
// Custom method, default timeout
// Configuration object pattern
function createServer({
port = 3000,
host = "localhost",
ssl = false,
verbose = false
}) {
console.log(`Server starting on ${host}:${port}`);
console.log(`SSL: ${ssl}, Verbose: ${verbose}`);
}
createServer({ port: 8080, ssl: true });
// Extract specific properties
function summarizeOrder({ id, total, items }) {
return {
orderId: id,
amount: total,
itemCount: items.length
};
}
let order = {
id: "ORD123",
total: 99.99,
items: ["item1", "item2", "item3"],
customer: "Alice",
date: new Date()
};
console.log(summarizeOrder(order));
// { orderId: "ORD123", amount: 99.99, itemCount: 3 }Practical Examples
Example 1: Flexible Calculator
function calculate(operation, ...numbers) {
switch (operation) {
case "add":
return numbers.reduce((sum, n) => sum + n, 0);
case "multiply":
return numbers.reduce((product, n) => product * n, 1);
case "average":
return numbers.reduce((sum, n) => sum + n, 0) / numbers.length;
case "max":
return Math.max(...numbers);
case "min":
return Math.min(...numbers);
default:
return "Unknown operation";
}
}
console.log(calculate("add", 1, 2, 3, 4, 5)); // 15
console.log(calculate("multiply", 2, 3, 4)); // 24
console.log(calculate("average", 10, 20, 30, 40)); // 25
console.log(calculate("max", 5, 10, 3, 8, 15)); // 15Example 2: User Management System
class UserManager {
constructor() {
this.users = [];
}
// Destructured parameters with defaults
addUser({
name,
email,
role = "user",
active = true,
permissions = ["read"]
}) {
const user = {
id: this.users.length + 1,
name,
email,
role,
active,
permissions,
createdAt: new Date()
};
this.users.push(user);
return user;
}
// Rest parameters for multiple IDs
activateUsers(...userIds) {
return userIds.map(id => {
const user = this.users.find(u => u.id === id);
if (user) {
user.active = true;
return `Activated user ${id}`;
}
return `User ${id} not found`;
});
}
// Flexible search with destructured options
findUsers({ role, active, minId = 0 } = {}) {
return this.users.filter(user => {
if (role && user.role !== role) return false;
if (active !== undefined && user.active !== active) return false;
if (user.id < minId) return false;
return true;
});
}
}
const manager = new UserManager();
manager.addUser({
name: "Alice",
email: "alice@test.com",
role: "admin"
});
manager.addUser({
name: "Bob",
email: "bob@test.com"
});
console.log(manager.findUsers({ role: "admin" }));
console.log(manager.activateUsers(1, 2));Parameters and Arguments Practice
Experiment with flexible function parameters
console.log() to see your output in the console above.Key Takeaways
- Parameters are variables in function definition; arguments are values passed when calling
- Default parameters:
function(a = 5)provide fallback values - Rest parameters:
function(...args)collect remaining arguments into array - Rest parameter must be last parameter
- Arguments object exists in regular functions but not arrow functions
- Prefer rest parameters over arguments object (cleaner, real array)
- Destructuring parameters:
{ name, age }extract properties directly - Can combine default parameters with destructuring
- Missing arguments become
undefined; extra arguments ignored - Modern JavaScript favors rest parameters and destructuring for flexible functions
What's Next?
You now understand how to create flexible functions with default parameters, rest parameters, and destructuring! These features make JavaScript functions incredibly versatile and easy to use.
In the next lesson, we'll explore Return Statements and Values—learning how functions send data back, early returns, and what happens when there's no return statement. Essential for understanding function output!
💪 Practice Challenge:
Before moving on, try creating:
- A function that uses rest parameters to find the average of any number of values
- A function with destructured parameters for creating a product object
- A function that combines default parameters, rest parameters, and destructuring
- A flexible logger function that accepts a message and any number of details
- A configuration function with nested destructuring and defaults