我的广泛问题是区分JavaScript中递归函数的初始和连续调用的最简单方法。
Lemme举个例子......
如果在初始调用中传递给函数的字符串为空,我希望以下函数返回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('');
}
但是我把它重新定义为一个递归函数来解决更广泛的问题......
答案 0 :(得分:3)
不要试图区分不同的调用 - 函数的结果不应该依赖于副作用,也不应该在调用堆栈上。
相反,使用第二个执行不同功能的函数:
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);
}
答案 1 :(得分:0)
您可以使用嵌套函数,即使名称相同:
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;
}
答案 2 :(得分:0)
这与Bergi的答案基本相同,但是在 isPalindrome 中声明了辅助函数,因此它不会在其他地方使用。
回文的一个更好的例子是,应删除所有标点符号,并将字母全部用大写或小写(以便比较不区分大小写),但仅限于第一次调用。在那之后,比较字符很简单。
长度==零部分也只处理一次,如果没有可供比较的字符,则不会递归调用该函数。
以下进行初始处理,然后调用内部函数。
使用函数声明而不是命名函数表达式,因为后者具有undesirable side effects in 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