初学者javascript-er here ...
我遇到了一个问题,我不得不使用递归来查明给定的数字(n)是否是偶数。这是我的解决方案 - 通过所有测试 - 但我想知道一个单词"返回"需要 - 见下面的评论:
User
答案 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
)