如何访问 Javascript 中函数的 return 语句

How to access the return statement of a function in Javascript

我正在寻找一种方法来获取 Javascript 中函数的 return 表达式。我希望将它作为字符串获取,但任何类型都可以。另外,我正在寻找一种方法来设置函数的 return 语句而不影响它的其余部分。

示例:

let f1 = () => {
    let x = 1
    return 2 + x
}

let f2 = () => {
    let y = 2
    return 3 + y
}

let s = f1.getReturnExpression()
console.log(s) // 2 + x

f2.setReturnExpression(s)
console.log(f2.toString()) // "function f2() {  let y = 2; return 2 + x; }

我不确定这是最好的方法,但要获得 return 值,您可以简单地执行以下操作:functionName.toString().split('return ')[1].split(';')[0].

要更改第二个功能,您可以执行以下操作:let secondFunction = new Function(string)

对于字符串,您需要删除 {} 和 return 之后的值(这需要使用正则表达式和替换方法来完成,但我不擅长这个。)

要删除 {},您可以这样做:functionName.toString().slice(functionName.toString().indexOf('{') + 1, functionName.toString().lastIndexOf('}'))

希望对您有所帮助。

提取 return 语句应该是 "easy" 但我不确定如何在运行时重建新函数并将其分配给现有函数而不以某种方式损坏范围。

假设现在提取 return 语句就足够了。我绝对不建议为此使用正则表达式或字符串操作;你会弄错的。

您应该使用像 这样的工具,这些工具允许您将一段代码解构为您可以检查的数据结构。

给定以下函数:

function foo(x) {
  if (x) {
    return x + 10;
  } else {
    return x - 10;
  }
}

传递给esprima:

esprima.tokenize(foo.toString());

这是你得到的:

[ { type: 'Keyword', value: 'function' },
  { type: 'Identifier', value: 'foo' },
  { type: 'Punctuator', value: '(' },
  { type: 'Identifier', value: 'x' },
  { type: 'Punctuator', value: ')' },
  { type: 'Punctuator', value: '{' },
  { type: 'Keyword', value: 'if' },
  { type: 'Punctuator', value: '(' },
  { type: 'Identifier', value: 'x' },
  { type: 'Punctuator', value: ')' },
  { type: 'Punctuator', value: '{' },
  { type: 'Keyword', value: 'return' },
  { type: 'Identifier', value: 'x' },
  { type: 'Punctuator', value: '+' },
  { type: 'Numeric', value: '10' },
  { type: 'Punctuator', value: ';' },
  { type: 'Punctuator', value: '}' },
  { type: 'Keyword', value: 'else' },
  { type: 'Punctuator', value: '{' },
  { type: 'Keyword', value: 'return' },
  { type: 'Identifier', value: 'x' },
  { type: 'Punctuator', value: '-' },
  { type: 'Numeric', value: '10' },
  { type: 'Punctuator', value: ';' },
  { type: 'Punctuator', value: '}' },
  { type: 'Punctuator', value: '}' } ]

这是 JavaScript 数据结构中的函数 foo,您可以在... JavaScript...
A m a z i n g

现在应该很明显地找出如何提取两个可能的 return 语句。
但是,重要的是要注意我确实假设每个 return语句以分号 ;.

结尾

为了识别 return 语句的开始,我们可以编写一个 isReturnStatement 函数:

const isReturnStatement = token =>
  token.type === 'Keyword' &&
  token.value === 'return';

为了识别这种语句的结束,我们可以写一个isEndOfStatement函数:

const isEndOfStatement = token =>
  token.type === 'Punctuator' &&
  token.value === ';';

如您所见,您现在正在处理一个 JavaScript 数据结构,一个标记数组。每个标记代表一段代码语法。

您现在需要确定 return 语句的开始和结束。保存并继续该过程,直到您检查了整个阵列。

这是一种方法:

function foo(x) {
  if (x) {
    return x + 10;
  } else {
    return x - 10;
  }
}

const ast = esprima.tokenize(foo.toString());

console.log(

  getReturnStatements(ast)
  
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/esprima/2.7.3/esprima.min.js"></script>

<script>

const isReturnStatement = token =>
  token.type === 'Keyword' &&
  token.value === 'return';

const isEndOfStatement = token =>
  token.type === 'Punctuator' &&
  token.value === ';';

const getReturnStatements = ast => {
  const scan = ast.reduce((search, token) => {
    if (isReturnStatement(token)) {
      search.capture = true;
      search.stmt.push('');
    } else if (search.capture && !isEndOfStatement(token)) {
      search.stmt[search.stmt.length - 1] += token.value;
    } else {
      search.capture = false;
    }
    return search;
  }, {capture: false, stmt: []});
  return scan.stmt;
};

</script>

请注意,为了提高准确性,您应该解析代码而不是对其进行标记化,但我希望这能为您提供一个良好的开端。