简单函数返回'undefined'值

时间:2014-01-17 05:21:23

标签: javascript recursion

这是我目前正在进行的工作:

function getSmallestDivisor(xVal) {    

    if (xVal % 2 === 0) {
        return 2;
    } else if (xVal % 3 === 0) {
        return 3;
    } else {
        var xSqrt = Math.sqrt(xVal);

        if (xSqrt % 1 === 0) {
            getSmallestDivisor(xSqrt);
        } else { 
            return xVal;
        }
    }

}

alert(getSmallestDivisor(121));

我设计了上面的函数来返回整数的最小除数。考虑案例121。它实际上应该在当前上下文中返回11。但它正在返回undefined

我已经检查过递归调用的次数;他们实际上发生了两次。我在这两个不同的调用中记录了xVal的值,并显示12111。我真的很困惑,为什么这个函数当前正在返回undefined

我创建了a jsfiddle demo

6 个答案:

答案 0 :(得分:23)

其他人给出了正确的答案,但我想明确为什么,因为对某些人来说可能并不明显(不是针对OP)。

一个功能只不过是计算机采取的一系列步骤。

这称为函数调用

getSmallestDivisor(121)

无论何时使用return关键字,函数都会停止,函数调用替换为返回单词之后的任何内容(可能没有任何内容)。

所以在这种情况下,原始函数的问题是当脚本到达这一行时......

getSmallestDivisor(xSqrt);

...它返回11 那个函数调用,它永远不会返回到alert()内发生的原始函数调用。

因此,解决方案只是在它自己调用的地方之前添加return

return getSmallestDivisor(xSqrt);

这是制作递归函数时常见的错误。帮助弄清楚发生了什么的好方法是广泛使用browser console

function getSmallestDivisor(xVal) {    
    console.log("This is xVal: " + xVal);
    if (xVal % 2 === 0) {
        console.log("xVal % 2 === 0 was true");
        return 2;
    }
    else if (xVal % 3 === 0) {
        console.log("xVal % 3 === 0 was true");
        return 3;
    }
    else {
        console.log("This is else.");
        var xSqrt = Math.sqrt(xVal);
        console.log("This is xSqrt of xVal: " + xSqrt);
        if (xSqrt % 1 === 0) {
            console.log("xSqrt % 1 === 0 was true... recursing with xSqrt!!!");
            getSmallestDivisor(xSqrt);
        }
        else {
            console.log("This is the else inside of else. I am returning: " + xVal);
            return xVal;
        }
    }
}
var y = getSmallestDivisor(121);
console.log("This is y: " + y);

现在在您的浏览器中,您可以open the console(Chrome / Mac上的Option + Command + J)并观察正在发生的事情 - 执行哪些部分等等。

答案 1 :(得分:20)

if (xSqrt % 1 === 0) {
    return getSmallestDivisor(xSqrt); // missing return here
} else {
    return xVal;
}

演示:Fiddle

答案 2 :(得分:3)

只是评论。

由于每个if..else块都包含一个返回,因此该函数可以重构为仅使用块:

function getSmallestDivisor(xVal) {    

    if (!(xVal % 2)) return 2;

    if (!(xVal % 3)) return 3;

    var xSqrt = Math.sqrt(xVal);

    if (!(xSqrt % 1)) return getSmallestDivisor(xSqrt);

    return xVal;
}

function getSmallestDivisor(v, x) {    
    x = Math.sqrt(v);
    return !(v % 2)? 2 : !(v % 3)? 3 : !(x % 1)? getSmallestDivisor(x) : v;
}

答案 3 :(得分:1)

    if (xSqrt % 1 === 0) {
    // Because if your function walks this way 
    // it does not meet any 'return' statement
    // till the end and returns nothing. 
        getSmallestDivisor(xSqrt);
    } else {
        return xVal;
    }

答案 4 :(得分:0)

function getSmallestDivisor(xVal) {    
 if (xVal % 2 === 0) {
    return 2;
} else if (xVal % 3 === 0) {
    return 3;
} else {
    var xSqrt = Math.sqrt(xVal);
    alert("xSqrt--"+ xSqrt);
    if (xSqrt % 1 == 0) {
        return xSqrt;//line changed with else condition ,return xSqrt
    } else {
    getSmallestDivisor(xSqrt);//line changed with if condition

    }
}

}

我已对您的代码进行了一些更改,现在正在运行。

答案 5 :(得分:0)

我真的不能拒绝写这个……因为您的问题和所有答案对我有很大帮助。我遇到了完全相同的问题,我编写了递归函数,并省略了return关键字。此页面节省了我凝视编辑器的时间。

任务:

数字根是数字中所有数字的递归和。 给定n,取n的数字之和。如果该值超过一位,请继续以这种方式减少直到产生一位数字。

function digital_root(n) {
  if(n < 10) {
    return n;
  }
   let toString =  String(n);
   let splitted = toString.split('');
  
   let summArrayItems = function (arr) {
    let total = 0;
      for(let i = 0; i < arr.length; i++) {
        total += Number(arr[i]);
      }
      return total;
    }
  let output = summArrayItems(splitted);
  
  if(output < 10) {
   return output;
  } else {
    return digital_root(output); // In this line I omitted return keyword, and received undefined
  }
}