【问题标题】:Get function parameter length including default params获取函数参数长度,包括默认参数
【发布时间】:2017-03-20 08:42:57
【问题描述】:

如果您使用 Function.length 属性,您将获得该函数期望的参数总数。

但是,根据文档(以及实际尝试),它不包括计数中的默认参数。

这个数字不包括其余参数,只包括第一个参数之前的默认值 - Function.length

我是否有可能以某种方式获得包含默认参数的计数(从函数外部)?

【问题讨论】:

  • 一般来说,这样的问题最好把注意力集中在你试图解决的问题上。文档清楚地说明了真相,计数没有暴露,所以现在答案只是“否”,而如果你解释了你想做什么,人们将能够更有效地指导你。
  • 你不应该依赖Function.length。为什么?因为你会遇到麻烦——因为它已经发生了。
  • 你需要这个做什么?

标签: javascript node.js ecmascript-6


【解决方案1】:

也许你可以自己解析,比如:

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

【讨论】:

  • 当你在默认初始化程序中有一个函数(或任何带有逗号和括号的东西)时,这不起作用
  • @Bergi 我试图在我对类似问题的回答中解决这个问题:stackoverflow.com/a/51850585/1687909
  • @Mogzol 您可能想在此处发布您的答案(我已将另一个作为副本关闭)
【解决方案2】:

将我的答案从duplicate question 复制到这里:

嗯,这有点乱,但我相信这应该涵盖大多数边缘情况。

它的工作原理是将函数转换为字符串并计算逗号,但忽略字符串、函数调用或对象/数组中的逗号。我想不出任何情况下这不会返回正确的金额,但我确信有一个,所以这绝不是万无一失的,但在大多数情况下应该可以工作。

更新:有人向我指出,这不适用于 getNumArgs(a => {})getNumArgs(function(a){}.bind(null)) 等情况,因此如果您尝试使用它,请注意这一点。

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;
}

这是我尝试过的一些测试:https://jsfiddle.net/ekzuvL0c/

【讨论】:

    【解决方案3】:

    这是一个检索函数(表达式或对象)或箭头函数表达式 (afe) 的“长度”的函数。它使用正则表达式从字符串化函数/afe (在 () 或 => 之前的部分)中提取参数部分,并使用正则表达式来清除字符串的默认值。清理后,它计算逗号,具体取决于参数字符串中的括号。

    注意这始终是一个近似值。有一些边缘情况不会被覆盖。查看Stackblitz snippet中的测试

    const determineFnLength = fnLenFactory();
    
    console.log(`fnTest.length: ${determineFnLength(fnTest)}`);
    
    function fnTest(a, 
      b, 
      c = 'with escaped \' quote and, comma', 
      d = "and double \" quotes, too!" ) { console.log(`test123`); }
    
    function fnLenFactory() {
      const fnExtractArgsRE = /(^[a-z_](?=(=>|=>{)))|((^\([^)].+\)|\(\))(?=(=>|{)))/g;
      const valueParamsCleanupRE = /(?<=[`"'])([^\`,].+?)(?=[`"'])/g;
      const countArgumentsByBrackets = params => {
        let [commaCount, bracketCount, bOpen, bClose] = [0, 0, [...`([{`], [...`)]}`]];
        [...params].forEach( chr => {
          bracketCount += bOpen.includes(chr) ? 1 : bClose.includes(chr) ? -1 : 0;
          commaCount += chr === ',' && bracketCount === 1 ? 1 : 0; } );
        return commaCount + 1; };
      const extractArgumentsPartFromFunction = fn => {
        let fnStr = fn.toString().replace(RegExp(`\\s|function|${fn.name}`, `g`), ``);
        fnStr = (fnStr.match(fnExtractArgsRE) || [fn])[0]
                  .replace(valueParamsCleanupRE, ``);
        return !fnStr.startsWith(`(`) ? `(${fnStr})` : fnStr; };
    
      return (func, forTest = false) => {
        const params = extractArgumentsPartFromFunction(func);
        const nParams = params === `()` ? 0 : countArgumentsByBrackets(params);
        return forTest ? [params, nParams] : nParams;
      };
    }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-19
      • 2020-09-24
      • 2018-04-27
      相关资源
      最近更新 更多