递归和"返回" Javascript中的语句

时间:2018-06-07 04:28:32

标签: javascript recursion

初学者javascript-er here ...

我遇到了一个问题,我不得不使用递归来查明给定的数字(n)是否是偶数。这是我的解决方案 - 通过所有测试 - 但我想知道一个单词"返回"需要 - 见下面的评论:

User

4 个答案:

答案 0 :(得分:3)

  

这是我的问题 - 你能解释为什么这里需要'返回'吗?

它与函数调用有关,以及函数的结果如何传递回调用者。

暂时忘记递归,让我们看看一对函数。

function foo() {
  return 'foo for you';
}

function bar() {
  foo();
}

如果我这样打bar()会发生什么:

console.log(bar());

预期产出:

'undefined'
执行

foo(),但忽略函数调用的结果(例如,不保存到变量,也不返回)。 bar()没有explict return语句,因此ECMA规范使用了隐式return undefined;

查看调用堆栈(请注意,这类似于堆栈数据结构,当前函数调用位于堆栈顶部):

foo() ==> returns 'foo for you'
bar() ==> returns 'undefined'

这导致undefined被传递到控制台输出功能。

如果我们这样修改bar()

function bar() {
 return foo();
}

我们的输出更改为:

'foo for you'

foo()的结果作为bar()检查调用堆栈的结果返回

foo() ==> returns 'foo for you'
bar() ==> returns foo() which returns 'foo for you'

回到你的递归示例,没有return语句,它将执行,但执行的结果将不会传递给调用堆栈。

让我们假装缺少return语句,并在n = 4时检查callstack。

isEven(0) ==> returns true
isEven(2) ==> returns undefined
isEven(4) ==> returns undefined

isEven(4) = undefined. ERROR.

最终期望值true永远不会传递给callstack。

如上所述,使用返回值,结果如下:

isEven(0) ==> returns true
isEven(2) ==> returns isEven(0) which returns true
isEven(4) ==> returns isEven(2) which returns isEven(0) which returns true

isEven(4) = true PASSED.

答案 1 :(得分:1)

isEven(n - 2)被调用并进行评估。

一旦完成,调用者函数将进行评估,并将其返回给调用者。

答案 2 :(得分:1)

通过递归电话,你得到了#34; up" callstack:

--> isEven(6) --> isEven(4) --> isEven(2) --> isEven(0)

现在你来自上方的return true

--> isEven(6) --> isEven(4) --> isEven(2) --> isEven(0)
  ? <--                                   <-- true

但这还没有达到原来的来电者。所以我们必须从isEven(2)返回它,以便它到达调用者:

--> isEven(6) --> isEven(4) --> isEven(2) --> isEven(0)
 true <-     <--           <--           <--

答案 3 :(得分:0)

JavaScript是一种多范式语言,因此,您可以编写各种样式的有效JavaScript程序。

在较旧的JavaScript程序中,函数只能使用function语法声明,该语法在两个花括号{ ... }之间定义了一个函数体。

函数体由语句组成。一个这样的语句是return语句,它允许函数返回一个值。如果没有return语句,函数将始终返回undefined

因此,从一个角度来看,您可以说“您需要return语句,否则您将获得undefined”,但从另一个角度来看,您可以说“您正在使用function语法,因此,如果您期望返回值,则必须使用return

替代方案是在较新的JavaScript程序(ES6及更高版本)中可用的语法,称为arrow functions。箭头函数可以接受传统的函数体,其语句就像我们上面谈到的那样。但是箭头函数也可以使用单个表达式作为正文来编写,其中隐含return

// function syntax
var f = function () { return 1 }

// arrow syntax with body
var f = () => { return 1 }

// arrow syntax with implied return   
var f = () => 1

如果您可以设法使用表达式编写函数,则不必担心与return等语句相关的所有奇怪行为。

为了在下面做出逻辑决定,我们使用ternary expression。与if语句不同,三元表达式计算为一个值,当与箭头函数结合使用时,我们可以将逻辑分支想象为每个都具有自己的隐式return。 ..

const isEven = (n) =>
  n === 0
    ? true         // implicit return
  
  : n === 1
    ? false        // implicit return
  
  : isEven (n - 2) // implicit return
  
console.log
  ( isEven (0)  // true
  , isEven (1)  // false
  , isEven (2)  // true
  , isEven (3)  // false
  , isEven (4)  // true
  , isEven (5)  // false
  )

当然这只是一种方式。这是另一个

const isEven = (n) =>
  n < 2
    ? !Boolean (n)
    : isEven (n - 2)

console.log
  ( isEven (0)  // true
  , isEven (1)  // false
  , isEven (2)  // true
  , isEven (3)  // false
  , isEven (4)  // true
  , isEven (5)  // false
  )

另一个使用mutual recursion

const isEven = (n) =>
  n === 0
    ? true
    : isOdd (n - 1)
    
const isOdd = (n) =>
  n === 0
    ? false
    : isEven (n - 1)

console.log
  ( isEven (0)  // true
  , isEven (1)  // false
  , isEven (2)  // true
  , isEven (3)  // false
  , isEven (4)  // true
  , isEven (5)  // false
  )
  
console.log
  ( isOdd (0)  // false
  , isOdd (1)  // true
  , isOdd (2)  // false
  , isOdd (3)  // true
  , isOdd (4)  // false
  , isOdd (5)  // true
  )