user625860
user625860

Reputation:

Set undefined parameters via arguments

I'm trying to write a function that corrects the arguments of a function based on previously specified optional parameters. I've come to a problem though. It seems that I can't set variables via the arguments array unless they have been defined in any way before. The code below shows an example of the problem I'm facing.

function foo(a, b, c) {
    arguments[0] = "lorem";
    arguments[1] = "ipsum";
    arguments[2] = "dolor";

    console.log([a, b, c]);
}

foo(null);              // ["lorem", undefined, undefined]
foo(null, null);        // ["lorem", "ipsum",   undefined]
foo(null, null, null);  // ["lorem", "ipsum",   "dolor"]

When logging arguments the result is always ["lorem", "ipsum", "dolor"] though.
Is there any way to solve this problem ?

I can't set a, b and c directly because a function called in foo wouldn't have access to these names.
My goal would look like something like this:

function foo(a, b, c) {
    var rules = [];
    // Rule for optional parameter 1 (b)
    // If it equals true the value of b is shifted to the next parameter (c)
    rules[1] = function(val) { return val !== "ipsum"; };
    optionalize(rules);

    console.log([a, b, c]);
}

foo("lorem", "dolor"); // ["lorem", undefined, "dolor"];

Upvotes: 1

Views: 93

Answers (4)

Ryan Stein
Ryan Stein

Reputation: 8000

It is a bit peculiar, but is this what you had in mind?

function optionalize(fn, options) {
    var i, key, rule;
    for(i = 0; i < options.length; i += 1) {
        key = fn.placement[i];
        rule = fn.ruleset[key];

        // If the rule exists and returns true, shift value to the right.
        if(rule && rule(options[i])) {
            options[i+1] = options[i];
            options[i] = undefined;
        }

        // Assign the numeric index to an alphabet key.
        // Depending on your use case, you may want to substitute a plain Object here and return that, instead of adding non-numeric properties to an Array.
        options[key] = options[i];
    }
}

// Test function
function foo(a, opts) {
    opts = opts || [];
    optionalize(foo, opts);

    console.log([a, opts.b, opts.c]);
}

// Optional argument names, in the order that they would be received.
foo.placement = ['b', 'c'];

// Optionalize rules
foo.ruleset = {
    b: function (val) { return val !== "ipsum"; }
};


// Demonstration
foo('lorem');
foo('lorem', []);
foo('lorem', ['dolor']);
foo('lorem', ['ipsum', 'dolor']);

As dystroy's answer has already indicated, the arguments variable isn't a real Array, and changing it may not be a good idea. I have provided a solution which does not rely on arguments and fulfills the criteria as far as could be possible using simple JavaScript.

The function foo is specified with a required argument a, followed by an Array of optional arguments named opts. An optionalize specification is set onto foo, through the placement and ruleset properties. The optionalize function takes this information and transforms the array's indices into usable name keys, applying the rules as necessary.

Upvotes: 0

epascarello
epascarello

Reputation: 207501

You can convert arguments to an array

function foo () {
     var arguments = Array.prototype.slice.call(arguments);
     arguments.push(4);
     console.log(arguments);
}
foo(1,2,3);

Upvotes: 0

Denys S&#233;guret
Denys S&#233;guret

Reputation: 382122

The arguments array isn't really an array but an "array-like" object. You can't change its length.

What you try to do is usually done using

a = a || "lorem";

or, if you don't want to replace any "falsy" argument, using

if (typeof a === "undefined") a = "lorem";

Upvotes: 1

Pierre Arlaud
Pierre Arlaud

Reputation: 4133

I'm not sure what you're trying to do but something like arguments[0] = a ? a : "lorem" and so on ?

Upvotes: 0

Related Questions