【问题标题】:What's wrong with return here?返回这里有什么问题?
【发布时间】:2016-04-11 05:11:25
【问题描述】:

我正在通过雄辩的 javascript 工作,无论出于何种原因,return 根本无法在函数 nth 中工作。 老实说,我不明白为什么它不起作用。我知道我已经非常接近在第 n 次工作的递归版本了。这个错误对我来说毫无意义。 以下是所有相关代码:

function arrayToList(array) {
  list = null;
  for (i = 0; i < array.length; i++ ) {
    var x = array[array.length -(i + 1)];
    list = {value: x, rest: list};
  } return list;
}

function listToArray(list) {
  var array = [];
  var i = 0;
  for (var node = list; node; node = node.rest) {
    array[i] = node.value;
    i += 1;
  }
  return array;
}  


//return statements are broken here
function nth(list, number) {
 if (number == 0) {
   //console.log(list.value);
   return element;
   var element = list.value;
   } else if (number > 0) {
     list = list.rest;
     number--;
     //console.log(number);
     //console.log(list);
     nth(list, number);
   } else {
     return "Something went wrong";
     console.log(number);
   }
}

console.log(nth(arrayToList([10, 20, 30]), 1));

谁能解释为什么 return 语句在第 n 个函数中不起作用?

【问题讨论】:

  • 你的缩进好像有点不对...
  • return nth(list, number); in else if
  • 函数调用正常。我移动了缩进,这似乎不是问题。
  • 您应该使用 var 将所有这些变量保留在本地:for (i=0 ...) 不是雄辩的。
  • 我认为 for(i = 0 ...) 是本地的

标签: javascript if-statement return


【解决方案1】:

您可以通过删除 var 并使用三元表达式来防止这两个问题(在错误位置声明的 var 元素和缺少返回)。这是一般的编码风格建议:少var 和少return => 少麻烦。 您的函数归结为单行:

function nth(list, number) {
  return number <= 0 ? list.value : nth(list.rest, number-1);
}

【讨论】:

  • 伙计......没有解释就投反对票是没有帮助的。
  • 不是我的反对票,但仅代码的答案没有帮助。您需要解释为什么 OP 有问题以及您的代码如何修复它。
  • 它应该是nth(list.rest, --number),因为number-- 在将变量值传递给函数后递减数字。此外,第一行的语句(例如 if (number &lt; 0 || !list) return;)将避免索引越界问题。也不是我的反对
  • @RobG @br3nt 感谢您的 cmets,我会改进答案。我想问题已经解释过了,没必要再重复了。 @br3nt “索引越界问题”:如果数字 nth 将返回 undefined,因此无需进行特定检查。
【解决方案2】:

为了返回“出现问题”,您需要在访问其属性之前检查list 是否不为空。实际上,这会检查 number 是否没有超过其上限,如果超过则避免抛出 TypeError。例如并包括检查number 的下限,

function nth(list, number) {
    if( number < 0 || !list)
        return "Something went wrong";
    if (number == 0) {
        return list.value;
    }
    return nth(list.rest, --number);
 }

在返回语句之前设置element(上面没有使用)和递归调用返回值(如上)的问题已经在cmets和answers中讨论过。

【讨论】:

    【解决方案3】:

    您需要进行两项更改:

    function nth(list, number) {
      if (number == 0) {
        var element = list.value; // <- this goes above the return
        return element;
      } else if (number > 0) {
        list = list.rest;
        number--;
        return nth(list, number); // <- you need to add a return statement here
      } else {
        return "Something went wrong";
      }
    }
    

    有了这个变化:

    console.log(nth(arrayToList([10, 20, 30]), 0)); // returns 10
    console.log(nth(arrayToList([10, 20, 30]), 1)); // returns 20
    console.log(nth(arrayToList([10, 20, 30]), 2)); // returns 30
    

    您基本上是在使用递归对链表进行迭代。 number 是您要跳过的节点数。如果number 为 0,我们希望返回该值。如果number 为1,我们想跳过一个节点。这就是您代码的else if 部分正在执行的操作。它正在跳过当前节点,并返回其余节点。

    要跳转到下一个节点,请执行nth(list.rest, --number)。你不断地这样做,直到数字达到 0,这会得到你真正想要的值。

    最终当number 为1 时,代码中else if 部分的return 语句将是return nth(list.rest, 0),它返回您想要的实际值。这就是您返回该值的原因。

    只是为了好玩,这里有一个不使用递归的版本:

    function nth(list, number) {
      if (number < 0) return;
    
      for (var curr = list; curr && number > 0; number--) {
        curr = curr.rest;
      }
    
      if (curr) return curr.value;
    }
    

    【讨论】:

    • 谢谢。你能解释一下为什么我需要 return 来再次调用该函数吗?我不明白为什么我需要进行这两项更改,没有它,该函数会正确调用自身。
    • 您基本上是在使用递归遍历链表。 Number 是您要跳过的节点数...所以要跳到下一个节点,您需要执行 nth(list.rest, --number)... 并且您不断执行此操作,直到 number 达到 0。这就是您最终想要的值。因为递归,return 语句最终会返回正确的值,因为你最终会到达返回实际值的nth(list.rest, 0)
    【解决方案4】:

    您的代码实际上存在 2 个问题。
    看小提琴:https://jsfiddle.net/0wpdnn66/

    • 您必须在使用之前定义元素(交换第 24 行和第 25 行)
    • 您需要从所有分支机构返回。第 31 行缺少return

    function arrayToList(array) {
      list = null;
      for (i = 0; i < array.length; i++ ) {
        var x = array[array.length -(i + 1)];
        list = {value: x, rest: list};
      } return list;
    }
    
    function listToArray(list) {
      var array = [];
      var i = 0;
      for (var node = list; node; node = node.rest) {
        array[i] = node.value;
        i += 1;
      }
      return array;
    }  
    
    
    //return statements are broken here
    function nth(list, number) {
     if (number == 0) {
       //console.log(list.value);
       var element = list.value;// <-- needs to be before return
       return element;
       } else if (number > 0) {
         list = list.rest;
         number--;
         //console.log(number);
         //console.log(list);
         return nth(list, number);// <-- needs return
       } else {
         return "Something went wrong";
         console.log(number);
       }
    }
    
    document.write(nth(arrayToList([10, 20, 30]), 1));

    【讨论】:

    • 谢谢。你能解释一下为什么我需要 return 来再次调用该函数吗?我不明白为什么我需要进行这两项更改,没有它,该函数可以正确调用自身。
    • 因为否则你会丢失函数的结果(它返回undefined
    • 它正在调用自己,但没有返回任何内容到您的原始调用。问题是递归调用的函数将(可能)返回一个值给你调用的函数。然后,您从递归循环外部调用的函数将必须返回结果。如果没有 return 语句,它将不会这样做。
    • 是否有资源可以解释退货的工作原理?我不知道它是这样做的
    • 好吧,我们所有人都会发生忽视的事情;)
    【解决方案5】:

    这样的事情会起作用

    function arrayToList(array) {
        var list = null;
        for (var i = 0; i < array.length; i++) {
            var x = array[array.length - (i + 1)];
            list = {
                value: x,
                rest: list
            };
        }
    
        return list;
    }
    
    //return statements are broken here
    function nth(list, nr) {
        if (nr === 0) {
            return list.value;
        } else if (nr > 0) {
            list = list.rest;
            nr--;
            return nth(list, nr);
        }
    }
    
    var list = arrayToList([10, 20, 30]);
    var nthNr = nth(list, 1);
    console.log(nthNr);
    

    【讨论】:

      【解决方案6】:

      你在给element赋值之前使用return,这意味着因为hoisting声明了element,但是undefined

      if (number == 0) {
         //console.log(list.value);
         return element;
         var element = list.value;
      

      应该是

      if (number == 0) {
         //console.log(list.value);
         var element = list.value;
      
         return element;
      

      因为我猜你只定义了元素以便在返回之前记录它,你可以更简单地做到这一点(正如Joe Frambach 指出的那样)

      if (number == 0) {
         return list.value;
      

      同样在下面else if需要返回nth的调用结果。

      这样就变成了

      } else if (number > 0) {
           list = list.rest;
           number--;
           //console.log(number);
           //console.log(list);
           return nth(list, number);
      

      【讨论】:

      • 或切入正题return list.value
      • 是的,这里似乎是合法的
      • 感谢您的回复。我更正了,返回仍然不起作用
      • @Steve 更新了我的答案
      • 该解决方案确实有效,但我不明白为什么我需要回电
      猜你喜欢
      • 1970-01-01
      • 2021-10-03
      • 1970-01-01
      • 2017-08-25
      • 2011-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多