我目前正在做一個 JavaScript 練習,需要我創建一個遞回函式,從起始數到結束數(包括)。我已經找到了解決方案,但我一直試圖讓我認為是同義的基本案例起作用,但我無法理解它。
function rangeOfNumbers(startNum, endNum) {
if (endNum < startNum) {
return [];
}
const arr = rangeOfNumbers(startNum, endNum - 1);
arr.push(endNum);
return arr;
};
console.log(rangeOfNumbers(1, 5)) = [1, 2, 3, 4, 5]
上面的代碼有效,但下面的代碼不起作用:
function rangeOfNumbers(startNum, endNum) {
if (endNum = startNum) {
return [endNum];
}
const arr = rangeOfNumbers(startNum, endNum - 1);
arr.push(endNum);
return arr;
};
console.log(rangeOfNumbers(1, 5)) = [1]
后者只輸出一個帶有startNum. 我很困惑為什么它不計算遞回的其他堆疊,有人可以向我解釋一下嗎?
uj5u.com熱心網友回復:
問題是您使用的是賦值運算子而不是相等運算子。
正確的
if (endNum === startNum)
不正確
if (endNum = startNum)
uj5u.com熱心網友回復:
您的第二個代碼塊不起作用的原因是因為該if (endNum = startNum)行。通過使用單個等號,您將分配startNum給endNum.
要檢查相等性,您可以使用相等運算子( ==) 或嚴格相等運算子( ===):
if (endNum === startNum) {
return [endNum]
}
uj5u.com熱心網友回復:
遞回是一種函式式遺產,因此以函式式風格使用它會產生最好的結果。這意味著避免諸如突變、變數重新分配和其他副作用之類的事情——
function rangeOfNumbers (startNum, endNum) {
if (startNum > endNum)
return []
else
return [startNum].concat(rangeOfNumbers(startNum 1, endNum))
}
console.log(JSON.stringify(rangeOfNumbers(0, 3)))
console.log(JSON.stringify(rangeOfNumbers(3, 7)))
console.log(JSON.stringify(rangeOfNumbers(9, 3)))
[0,1,2,3]
[3,4,5,6,7]
[]
使用函式式風格意味著你可以用一個函式呼叫來代替它的return值并且總是得到正確的結果。這使您能夠對程式進行推理,就好像它們是公式或方程式一樣。如果您使用命令式風格的遞回,這是不可能的 -
rangeOfNumbers(3,6)
== [3].concat(rangeOfNumbers(4,6))
== [3].concat([4].concat(rangeOfNumbers(5,6)))
== [3].concat([4].concat([5].concat(rangeOfNumbers(6,6))))
== [3].concat([4].concat([5].concat([6].concat(rangeOfNumbers(7,6)))))
== [3].concat([4].concat([5].concat([6].concat([]))))
== [3].concat([4].concat([5].concat([6])))
== [3].concat([4].concat([5,6]))
== [3].concat([4,5,6])
== [3,4,5,6]
您可以撰寫與純函式運算式相同的內容 -
const range = (start, end) =>
start > end
? []
: [start, ...range(start 1, end)]
console.log(JSON.stringify(range(0, 3)))
console.log(JSON.stringify(range(3, 7)))
console.log(JSON.stringify(range(9, 3)))
[0,1,2,3]
[3,4,5,6,7]
[]
這可以被形象化為——
range(3,6)
== [3, ...range(4, 6)]
== [3, ...[4, ...range(5, 6)]]
== [3, ...[4, ...[5, ...range(6, 6)]]]
== [3, ...[4, ...[5, ...[6, ...range(7, 6)]]]]
== [3, ...[4, ...[5, ...[6, ...[]]]]]
== [3, ...[4, ...[5, ...[6]]]]
== [3, ...[4, ...[5, 6]]]
== [3, ...[4, 5, 6]]
== [3, 4, 5, 6]
只需再多一個條件,我們也可以支持反向范圍 -
const range = (start, end) =>
start > end
? range(end, start).reverse()
: start == end
? [start]
: [start, ...range(start 1, end)]
console.log(JSON.stringify(range(0, 3)))
console.log(JSON.stringify(range(3, 7)))
console.log(JSON.stringify(range(9, 3)))
[0,1,2,3]
[3,4,5,6,7]
[9,8,7,6,5,4,3] // <- inverse
最后一個可以被形象化為——
range(9,6)
== range(6,9).reverse()
== [6, ...range(7,9)].reverse()
== [6, ...[7, ...range(8,9)]].reverse()
== [6, ...[7, ...[8, ...range(9,9)]]].reverse()
== [6, ...[7, ...[8, ...[9]]]].reverse()
== [6, ...[7, ...[8, 9]]].reverse()
== [6, ...[7, 8, 9]].reverse()
== [6, 7, 8, 9].reverse()
== [9, 8, 7, 6]
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/383319.html
標籤:javascript 递归
