{"id":580,"date":"2022-08-30T15:03:43","date_gmt":"2022-08-30T15:03:43","guid":{"rendered":"https:\/\/unknownerror.org\/index.php\/2013\/11\/09\/lightweight-javascript-module-for-optional-default-parameters-collection-of-common-programming-errors\/"},"modified":"2022-08-30T15:03:43","modified_gmt":"2022-08-30T15:03:43","slug":"lightweight-javascript-module-for-optional-default-parameters-collection-of-common-programming-errors","status":"publish","type":"post","link":"https:\/\/unknownerror.org\/index.php\/2022\/08\/30\/lightweight-javascript-module-for-optional-default-parameters-collection-of-common-programming-errors\/","title":{"rendered":"Lightweight JavaScript Module for Optional\/Default Parameters-Collection of common programming errors"},"content":{"rendered":"<p>Is there a JavaScript module that makes it easy to map arguments to parameters? Here is how I envision it working:<\/p>\n<blockquote>\n<p>var arguments = assignArguments(arguments, &#8216;p1&#8217;, &#8216;p2&#8217;, [{&#8216;p3&#8217;: 0}, &#8216;p4&#8217;], {&#8216;p5&#8217;: &#8216;unknown&#8217;});<\/p>\n<\/blockquote>\n<p>Within a function, you would call this to generate an object that associated a parameter with an argument. Parameters defined within an array or inline object would be considered optional, where inline objects would permit assigning default values. All other parameters are considered &#8220;required&#8221;.<\/p>\n<p>Here are some sample inputs\/outpus:<\/p>\n<pre><code>foo(1): { p1: 1, p3: 0, p5: 'unknown' } \/\/ no p2 (aka undefined) \nfoo(1, 2): { p1: 1, p2: 2, p3: 0, p5: 'unknown' } \nfoo(1, 2, 3): { p1: 1, p2: 2, p3: 0, p4: 3, p5: 'unknown' } \nfoo(1, 2, 3, 4): { p1: 1, p2: 2, p3: 3, p4: 4, p5: 'unknown' } \nfoo(1, 2, 3, 4, 5): { p1: 1, p2: 2, p3: 3, p4: 4, p5: 5 }\n<\/code><\/pre>\n<p>I am hoping a library like this already exists. This logic gets repeated a lot and I want to eliminate it if possible.<\/p>\n<p>Is anyone aware of a library like this? If not, can someone send me down the right path for implementing one?<\/p>\n<ol>\n<li>\n<p>I went ahead and thought of a way of doing this myself. It involves parsing an object graph made up of strings, arrays and objects. It&#8217;s quite long, but it works well.<\/p>\n<pre><code>function assignArguments(values, expression) {              \n    \/\/ determine how many arguments are needed for each parameter\n    \/\/ grab all of the defaults, too\n    var needed = 1;\n    var argsNeeded = {};\n    var defaults = {};\n    var queue = [expression];               \n    for (var queueIndex = 0; queueIndex &lt; queue.length; ++queueIndex) {\n        var node = queue[queueIndex];\n        if (typeof node === 'string') {\n            \/\/ the node is a required parameter\n            argsNeeded[node] = needed;\n            ++needed;\n        } else if (node instanceof Array) {\n            \/\/ the node is a list of parameters\n            for (var index = 0; index !== node.length; ++index) {\n                queue.push(node[index]);\n            }\n        } else {\n            \/\/ the node is a list of optional parameters with defaults\n            \/\/ make sure there isn't more than one parameter\n            var count = 0;\n            for (var key in node) {\n                if (node.hasOwnProperty(key)) {\n                    if (count !== 0) {\n                        throw new Error('A default parameter list had more than one value.');\n                    }\n                    defaults[key] = node[key];\n                    queue.push(key);\n                    ++count;\n                }\n            }\n        }\n    }\n\n    \/\/ determine the order that the parameters appear\n    var parameters = [];\n    var stack = [expression];\n    while (stack.length &gt; 0) {\n        var node = stack.pop();\n        if (typeof node === 'string') {\n            \/\/ the node is a required parameter\n            parameters.push(node);\n        } else if (node instanceof Array) {\n            \/\/ the node is a list of parameters\n            var index = node.length;\n            while (index !== 0) {\n                --index;\n                stack.push(node[index]);\n            }\n        } else {\n            \/\/ the node is an optional parameter with defaults\n            \/\/ we'll check for multiple parameters\n            var count = 0;\n            for (var key in node) {\n                if (node.hasOwnProperty(key)) {\n                    if (count &gt; 0) {\n                        throw new Error('A default parameter list had more than one value.');\n                    }\n                    stack.push(key);\n                    ++count;\n                }\n            }\n        }\n    }\n\n    var result = {};\n    var valueIndex = 0;\n    for (var index = 0; index !== parameters.length; ++index) {\n        var parameter = parameters[index];\n        var needed = argsNeeded[parameter];\n        if (needed &gt; values.length) {\n            if (parameter in defaults) {\n                result[parameter] = defaults[parameter];\n            }\n        } else {\n            result[parameter] = values[valueIndex];\n            ++valueIndex;\n        }\n    }\n\n    return result;\n}\n<\/code><\/pre>\n<p>And here is an example using it.<\/p>\n<pre><code>function foo() {\n    var params = assignArguments(arguments, ['p1', 'p2', [{p3:0}, 'p4'], {p5: 'unknown'}]);\n    return params;\n}\n\nconsole.log(foo(1));\nconsole.log(foo(1, 2));\nconsole.log(foo(1, 2, 3));\nconsole.log(foo(1, 2, 3, 4));\nconsole.log(foo(1, 2, 3, 4, 5));\n<\/code><\/pre>\n<\/li>\n<\/ol>\n<p id=\"rop\"><small>Originally posted 2013-11-09 21:05:29. <\/small><\/p>","protected":false},"excerpt":{"rendered":"<p>Is there a JavaScript module that makes it easy to map arguments to parameters? Here is how I envision it working: var arguments = assignArguments(arguments, &#8216;p1&#8217;, &#8216;p2&#8217;, [{&#8216;p3&#8217;: 0}, &#8216;p4&#8217;], {&#8216;p5&#8217;: &#8216;unknown&#8217;}); Within a function, you would call this to generate an object that associated a parameter with an argument. Parameters defined within an array [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-580","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/580","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/comments?post=580"}],"version-history":[{"count":0,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/580\/revisions"}],"wp:attachment":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/media?parent=580"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/categories?post=580"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/tags?post=580"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}