区分对递归函数的初始调用和连续调用
Differentiate between an initial and successive call to a recursive function
我的大问题是,在JavaScript中区分对递归函数的初始调用和连续调用的最简单方法是什么?
让我举个例子…
假设我希望下面的函数在初始调用中传递给函数的字符串为空时返回false。有没有一种方法可以做到这一点,而不添加另一个参数到函数?
function isPalindrome(str) {
if (str.length <= 1) {
return true;
}
if (str.charAt(0) !== str.charAt(str.length -1)) {
return false;
}
return isPalindrome(str.substr(1, str.length - 2));
}
isPalindrome('') // returns true, but I want this to return false
顺便说一句,我知道上面的函数可以更简单地写成:
function isPalindrome(str) {
return str == str.split('').reverse().join('');
}
但我将其重新定义为递归函数,以获得更广泛的问题…
不要试图区分不同的调用——函数的结果不应该依赖于副作用,更不应该依赖于调用堆栈。
相反,使用第二个函数来做一些不同的事情:function isPalindrome(str) {
return str.length <= 1 ||
str.charAt(0) == str.charAt(str.length-1) && isPalindrome(str.slice(1, -1));
}
function isNonEmptyPalindrome(str) {
return str.length > 0 && isPalindrome(str);
}
可以使用嵌套函数,甚至可以使用相同的名称:
function isPalindrome(str) {
// The code out here is for the initial call:
if (str === '')
return false;
// Then do the recursive call
return function isPalindrome(str) {
// within this scope, isPalindrome refers to this function
if (str.length <= 1) {
return true;
}
if (str.charAt(0) !== str.charAt(str.length -1)) {
return false;
}
return isPalindrome(str.substr(1, str.length - 2));
}(str); // call this function immediately
}
对于一般形式:
function name(arg) {
// Setup code before initial call
//////////////////////////////
var retVal = function name(arg) {
// recursive routine code
}(arg);
// Cleanup code after recursion completes
/////////////////////////////////////////
return retVal;
}
使用factorial
这与Bergi的答案本质上是相同的,但是在isPalindrome内部声明了辅助函数,因此它不会在其他地方使用。
回文的一个更好的例子是,所有的标点符号都应该被删除,字母都应该大写或小写(这样比较就不区分大小写了),但只在第一次调用时。在那之后,就是比较字符的简单问题了。
length == zero部分也只处理一次,如果没有剩余字符可供比较,则不会递归调用该函数。
下面的代码进行初始处理,然后调用内部函数。
使用函数声明代替命名函数表达式,因为后者在IE中有不良的副作用。
function isPalindrome(s) {
// Initial processing only on first call
// remove all punctuation
s = s.replace(/[^a-z0-9]/ig,'').toLowerCase();
return s.length == 0? false : doCheck(s);
function doCheck(s) {
if (s.length > 1) {
if (s.substr(0,1) == s.substr(s.length - 1, 1)) {
s = s.substr(1, s.length - 2);
return s.length? doCheck(s) : true;
} else {
return false;
}
}
return true;
}
}
console.log(isPalindrome("Madam I'm Adam")); // true
console.log(isPalindrome("Madam I'm Addam")); // false
相关文章:
- setTimeout()在其设置时间之前连续调用回调函数
- 为什么你不能通过连续调用 .text() JQuery 来逃避
- 连续的 ajax 调用会冻结 chrome 和 IE
- 每次提交时,Ajax 表单开始和成功处理程序的调用次数会连续增加
- Javascript For Loop - 播放列表中的连续 Ajax 调用
- 连续调用 javascript 函数,直到条件
- 连续调用多个函数
- 显示快速连续 AJAX 调用的结果
- 在jQuery UI中,如何防止连续调用时运行数百万次的“脉动”效应
- 处理快速连续的函数调用 - Javascript / underscore.js / node.js
- 在连续的AJAX调用上使用async
- javascript函数调用返回未定义和页面连续加载
- 如何在按下按钮并打洞时连续调用函数
- 一个HTML按钮可连续调用3个函数
- 与连续的setTimeout调用相比,setInterval更有可能按时发生
- 替代"async: false"用于连续的AJAX调用
- 我有连续的ajax调用,我如何用返回的数据构造一个表
- AngularJS连续的$http调用没有返回正确的数据
- 如何通过连续的AJAX调用来维护PHP对象
- 将连续调用的函数中的值保存到数组中