Aikido

Why you shouldn’t override function arguments: preventing confusion and debugging issues

Readability

Rule

Don't override function arguments.
Reassigning function parameters can confuse
callers and make debugging difficult.

Supported languages: 45+

Introduction

Reassigning function parameters changes the value of arguments within the function, making it unclear what value the parameter holds at any given point. When debugging, you can't trust that a parameter still contains the value passed by the caller. This creates confusion for anyone reading the code and makes tracking down bugs harder because the parameter's value changes throughout execution.

Code examples

❌ Non-compliant:

function processUser(user) {
    if (!user) {
        user = { id: null, name: 'Guest' };
    }

    user = { ...user, processedAt: Date.now() };

    if (user.age < 18) {
        user = { ...user, restricted: true };
    }

    return user;
}

Why it's wrong: The user parameter is reassigned multiple times, making it impossible to know what the original caller passed without reading the entire function. Debugging shows modified values, not the actual input, making it hard to trace issues back to the source.

✅ Compliant:

function processUser(user) {
    const currentUser = user || { id: null, name: 'Guest' };

    const processedUser = {
        ...currentUser,
        processedAt: Date.now()
    };

    if (currentUser.age < 18) {
        return { ...processedUser, restricted: true };
    }

    return processedUser;
}

Why this matters: New variables (currentUser, processedUser) hold intermediate values while the original user parameter remains unchanged. Debuggers show the actual input value, and the code clearly tracks transformations through named variables.

Conclusion

Use new variables for transformations instead of reassigning parameters. This makes data flow explicit and preserves the original input for debugging. The slight verbosity of extra variable declarations is outweighed by improved readability and debuggability.

FAQs

Got Questions?

What about default parameter values?

Default parameters (function process(user = {})) are different from reassignment. They only provide values when arguments are undefined, not reassign existing parameters. Use default parameters for optional arguments, but don't reassign them within the function body.

Does this apply to primitive vs object parameters?

Yes, both. Reassigning primitives (numbers, strings) changes the local reference and creates confusion. Reassigning objects completely replaces the reference, though mutating object properties (user.name = 'x') is a separate issue about immutability.

What if I need to normalize or clean input?

Create a new variable for the normalized value: const cleanedInput = normalizeInput(input). This makes it clear the function transforms input and shows both the original and cleaned values during debugging.

What about modifying parameter properties?

Modifying properties (user.name = 'x') is different from reassigning the parameter itself. However, mutating parameters is also problematic as it creates side effects. Prefer treating parameters as immutable and returning new objects with changes.

Get secure for free

Secure your code, cloud, and runtime in one central system.
Find and fix vulnerabilities fast automatically.

No credit card required | Scan results in 32secs.