Search code examples
javascriptecmascript-next

Change Values of All Variables Named via Function Signature


Let say I have a function that has 50 arguments, and I need to modify the values of each named-variable that was created inside the function's signature.

Instead of 50 arguments, he's an example with just 4:

// Each of these strings are padded with intentional and unnecessary whitespace:
let show = "  show ";
let me = " me  ";
let the = " the ";
let bunny = "  bunny   ";

function showMeTheBunny(show, me, the, bunny)
{
	// I want to trim each argument, without having to do this:
	show = show.trim();
	me = me.trim();
	the = the.trim();
	bunny = bunny.trim();
	// The above lines, within this function,
	// are the ones I want to replace with a loop (if possible)

	return `${show} ${me} ${the} ${bunny}: 🐇`; 
}
console.log(showMeTheBunny(show, me, the, bunny)); // output: "show me the bunny: 🐇"

The arguments object can access all the arguments passed into a function, but it doesn't seem to offer a way to change the values of the named-variables themselves.

Is it possible to run all the named-variables (named within a function signature) through a function that modifies each of them before consuming those modified arguments later (using the same variable names)?


Solution

  • You've said you want to modify the values of the "named variables" so I assume you mean the formal parameters (show, me, etc.)

    The arguments object can access all the arguments passed into a function, but it doesn't seem to offer a way to change the values of the named-variables themselves.

    It does, but only in loose mode, not strict mode:

    function showMeTheBunny(show, me, the, bunny)
    {
        for (let n = 0; n < arguments.length; ++n)
        {
            arguments[n] = arguments[n].trim();
        }
        return `${show} ${me} ${the} ${bunny}: 🐇`;
    }
    

    In that, arguments[0] = arguments[0].trim() updates the value of the show formal parameter, arguments[1] = arguments[1].trim() updates me, etc. But only in loose mode. In strict mode, only arguments[x] would be updated, not the formal parameter; the link back to it is removed. (It's worth noting that strict mode is the default in modules and class constructs.)

    Live Example:

    // Each of these strings are padded with intentional and unnecessary whitespace:
    let show = "  show ";
    let me = " me  ";
    let the = " the ";
    let bunny = "  bunny   ";
    
    function showMeTheBunny(show, me, the, bunny)
    {
        for (let n = 0; n < arguments.length; ++n)
        {
            arguments[n] = arguments[n].trim();
        }
    	return `${show} ${me} ${the} ${bunny}: 🐇`;
    }
    console.log(showMeTheBunny(show, me, the, bunny)); // output: "show me the bunny"

    There are other ways, but they wouldn't modify the values of the formal parameters. For instance, you could use a rest parameter:

    function showMeTheBunny(...rest)
    {
        rest = rest.map(entry => entry.trim());
        const [show, me, the, bunny] = rest;
        return `${show} ${me} ${the} ${bunny}: 🐇`;
    }
    

    Live Example:

    "use strict";
    // Each of these strings are padded with intentional and unnecessary whitespace:
    let show = "  show ";
    let me = " me  ";
    let the = " the ";
    let bunny = "  bunny   ";
    
    function showMeTheBunny(...rest)
    {
        rest = rest.map(entry => entry.trim());
        const [show, me, the, bunny] = rest;
    	return `${show} ${me} ${the} ${bunny}: 🐇`;
    }
    console.log(showMeTheBunny(show, me, the, bunny)); // output: "show me the bunny"

    That works in strict mode.

    Another option is to accept an object with properties for the parameters, then (again) use destructuring to get individual variables:

    function showMeTheBunny(args)
    {
        for (const [name, value] of Object.entries(args)) {
            args[name] = value.trim();
        }
        const {show, me, the, bunny} = args;
        return `${show} ${me} ${the} ${bunny}: 🐇`;
    }
    

    Live Example:

    "use strict";
    // Each of these strings are padded with intentional and unnecessary whitespace:
    let show = "  show ";
    let me = " me  ";
    let the = " the ";
    let bunny = "  bunny   ";
    
    function showMeTheBunny(args)
    {
        for (const [name, value] of Object.entries(args)) {
            args[name] = value.trim();
        }
        const {show, me, the, bunny} = args;
    	return `${show} ${me} ${the} ${bunny}: 🐇`;
    }
    console.log(showMeTheBunny({show, me, the, bunny})); // output: "show me the bunny"

    That also works in strict mode.