范围错误:超过了最大调用堆栈大小-JavaScript

时间:2020-07-10 23:43:14

标签: javascript closures higher-order-functions

我正在创建一个函数saveOutput,它接受一个函数和一个字符串。然后saveOutput将返回一个行为与传入函数完全相同的函数,除了将密码字符串作为参数传入时。发生这种情况时,返回的函数将返回一个对象,该对象将以前传入的所有参数作为键,并将相应的输出作为值。

我认为下面的代码是正确的,但是在运行代码时遇到了Range Error: Maxiumum call stack size exceeded

   function saveOutput(inputFunc, string) {
      let obj = {};
      //inputFunc() accepts one args
      //string like a pwd
     return function inputFunc(input) {
        if (input === string) {
            return obj;
             } else {
            obj[input] = inputFunc(input);
            return inputFunc(input);
        }
      }
      //returns a fxn
      return inputFunc;
   }

    //Test cases
    const multiplyBy2 = function(num) { return num * 2; };
    const multBy2AndLog = saveOutput(multiplyBy2, 'boo');
    console.log(multBy2AndLog(2)); // should log: 4
    console.log(multBy2AndLog(9)); // should log: 18
    console.log(multBy2AndLog('boo')); // should log: { 2: 4, 9: 18 }

1 个答案:

答案 0 :(得分:3)

您两次使用名称inputFunc。返回的函数称为inputFunc,因此它遮盖了作为参数传递的回调函数。返回的函数将调用inputFunc本身,该函数本身会导致无限递归,并最终引发“超出最大调用堆栈大小”错误。

要解决此问题,请使用其他名称或将其设为匿名(因为无论如何都不需要使用该名称),以下是经过改进的工作代码:

function saveOutput(inputFunc, string) {
  let obj = {};

  return function (input) {                    // make it anonymous
    if (input === string) {
      return obj;
    }
                                               // improvement 1: the else block can be omitted here
    return obj[input] = inputFunc(input);      // improvement 2: no need to call inputFunc twice, just assign and return at the same time 
  }

  // the return statement here is never reached because there is a return right before it so just remove it
}

在此处详细了解变量阴影:An example of variable shadowing in javascript

演示:

function saveOutput(inputFunc, string) {
  let obj = {};

  return function(input) {
    if (input === string) {
      return obj;
    }

    return obj[input] = inputFunc(input);
  }
}

const multiplyBy2 = function(num) {
  return num * 2;
};
const multBy2AndLog = saveOutput(multiplyBy2, 'boo');
console.log(multBy2AndLog(2));
console.log(multBy2AndLog(9));
console.log(multBy2AndLog('boo'));