Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get function parameter length including default params

If you make use of the Function.length property, you get the total amount of arguments that function expects.

However, according to the documentation (as well as actually trying it out), it does not include Default parameters in the count.

This number excludes the rest parameter and only includes parameters before the first one with a default value - Function.length

Is it possible for me to somehow get a count (from outside the function) which includes Default parameters as well?

like image 216
user2110845 Avatar asked Oct 17 '22 15:10

user2110845


2 Answers

Maybe you can parse it yourself, something like:

function getNumArguments(func) {
    var s = func.toString();
    var index1 = s.indexOf('(');
    var index2 = s.indexOf(')');
    return s.substr(index1 + 1, index2 - index1 - 1).split(',').length;
}

console.log(getNumArguments(function(param1, param3 = 'test', ...param2) {})); //3
like image 84
Arg0n Avatar answered Oct 31 '22 11:10

Arg0n


Copying my answer over to here from a duplicate question:

Well, it's a bit of a mess but I believe this should cover most edge cases.

It works by converting the function to a string and counting the commas, but ignoring commas that are in strings, in function calls, or in objects/arrays. I can't think of any scenarios where this won't return the proper amount, but I'm sure there is one, so this is in no way foolproof, but should work in most cases.

UPDATE: It's been pointed out to me that this won't work for cases such as getNumArgs(a => {}) or getNumArgs(function(a){}.bind(null)), so be aware of that if you try to use this.

function getNumArgs(func) {
  var funcStr = func.toString();
  var commaCount = 0;
  var bracketCount = 0;
  var lastParen = 0;
  var inStrSingle = false;
  var inStrDouble = false;
  for (var i = 0; i < funcStr.length; i++) {
    if (['(', '[', '{'].includes(funcStr[i]) && !inStrSingle && !inStrDouble) {
      bracketCount++;
      lastParen = i;
    } else if ([')', ']', '}'].includes(funcStr[i]) && !inStrSingle && !inStrDouble) {
      bracketCount--;
      if (bracketCount < 1) {
        break;
      }
    } else if (funcStr[i] === "'" && !inStrDouble && funcStr[i - 1] !== '\\') {
      inStrSingle = !inStrSingle;
    } else if (funcStr[i] === '"' && !inStrSingle && funcStr[i - 1] !== '\\') {
      inStrDouble = !inStrDouble;
    } else if (funcStr[i] === ',' && bracketCount === 1 && !inStrSingle && !inStrDouble) {
      commaCount++;
    }
  }

  // Handle no arguments (last opening parenthesis to the last closing one is empty)
  if (commaCount === 0 && funcStr.substring(lastParen + 1, i).trim().length === 0) {
    return 0;
  }

  return commaCount + 1;
}

Here are a few tests I tried it on: https://jsfiddle.net/ekzuvL0c/

like image 37
Mogzol Avatar answered Oct 31 '22 11:10

Mogzol