Args.js – Optional and Default parameters for JavaScript
autographer.github.io
autographer.github.io
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
I will have a look at providing a version that works in strict mode.
For me; one of the "joys" of coding JavaScript is the expressiveness that comes with a dynamic languages; should you throw an ArgumentError when your function that expects a number is invoked with a String? Maybe - sure it can help catch problems early and effectively "stop-the-line" in your public API, but then again it will probably end up throwing the classic `TypeError: Object foo has no method 'bar'` for you anyway.
For "public" methods which form part of an API (especially when that API is going to be shared outside of my team) I try to make my functions handle failure early (before they delegate off to the "private" internal methods), even better if the public methods can repair any unexpected usage, ie:
function convertToHex(value) {
var result;
if (typeof value !== "number") {
result = convertToHex(parseInt(value, 10));
}
else {
result = "0x" + value.toString(16);
}
return result;
}
Also, with regards to default argument values, I've always felt the "native" JavaScript approach was fairly compact and descriptive when required: function doFoo(bar) {
bar = (bar !== undefined) ? bar : "default_value";
}
[0] http://en.wikipedia.org/wiki/Duck_typing function doFoo(bar) {
bar = (bar !== undefined) ? bar : "default_value";
}
Over : function doFoo(bar) {
bar = bar || "default_value";
}
Coercion avoidance ? bar = bar != null ? bar : 'default';Keep in mind that you will have to go for the first option (or other better options) if you expect 'falsy' values to be passed as arguments.
Trusting you find Dart, Typescript, et al agreeable you have to concede that some people are working with legacy code and can only make iterative changes to their codebase?
0 - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
1 - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
var args = Args([ ... defs ... ], Array.prototype.slice.call(arguments));
The arguments object is not a real array, this is true, but it has a length and is indexable, so Args.js still works ok.
I have seen on MDN[0]:
> The arguments object is available only within a function body. Attempting to access the arguments object outside a function declaration results in an error.
It doesn't actually cause an error though, so am I misreading that? Besides, by that definition passing arguments to Array.prototype.slice.call() is also a no-no.
[0] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
> NOTE: The slice function is intentionally generic; it does not require that its this value be an Array object. Therefore it can be transferred to other kinds of objects for use as a method. Whether the slice function can be applied successfully to a host object [ed: 'arguments' is one such] is implementation-dependent. [0]
'arguments' isn't just array-like. It's got some very weird behavior. For instance, if your function also has named parameters, and you set an index on the arguments object that corresponds with a parameter, then it changes the value of the local parameter as well.
"Non-standard This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future."
Args([/* argument definition */], arguments);
That and I'm not understanding from the page how this is used in the first place. Is the `arguments` implicit variable being passed in some place? (EDIT: yes, via `Function.caller`.) Are the argument values accessed through the result of calling `Args`?
For a non-macro implementation of this, it might be interesting to use function decorator syntax instead, to put the argument processing outside the function body entirely. Basically, the argument processor decorator function would take an options array and a target function, which has all possible parameters, explicitly named. The decorator would spit out a new function that invisibly does all of the wrangling of `arguments` and then finally calls the target function. An advantage is that I think this would be the most minimal pure JS solution from a syntax perspective, and it would keep the actual function body uncluttered. A disadvantage is that it could only really be used with function expressions (not declarations).
Its not hard, and doesn't require much, if any, more code than the config options for libraries like this to just handle your arguments normally.
required arguments get defined in your function signature. You assign optional args to local variables defined within your function body via the arguments object. It's pretty easy.
For functions with longer parameter lists this should hopefully be more readable too. It's clear what types can be passed to a function.
Out of interest, what other libraries like this have you seen? I did a quick check myself and couldn't find anything comparable.
this.define('isFemale', female, String.Boolean);
should be this.define('isFemale', female, Strict.Boolean);