Reputation:
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
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
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
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
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