JavaScript循环跳过特定索引:字符串排列代码为何遗漏第二个字符?
问题原因分析:全局循环变量导致的逻辑错误
嘿,我一眼就发现问题所在了——你的代码里的循环变量i和j都没有用块级作用域声明,全部变成了全局变量,这就是循环跳过第二个字符的核心原因!
具体问题拆解
我们来看代码里的几个循环:
addNew函数内的for(i=0;i<=arr.length;i++):这里的i没有用var/let/const声明,会自动挂载到全局作用域。- 外层的
for(i=0;i<chars.length;i++):同样使用了未声明的全局i。 - 内层的
for(j=0;j<temp.length;j++):j也是未声明的全局变量。
当代码执行到第一次外层循环(处理第一个字符)时,会调用addNew函数,而addNew里的循环会修改全局的i值。等addNew执行完毕,全局i已经被更新到超出当前外层循环的预期值了——比如处理"abcd"的第一个字符'a'时,addNew里的循环结束后i会变成1,此时外层循环的i++会直接把i变成2,跳过了i=1的循环(也就是第二个字符'b'完全没被处理)。
后续循环只会处理第三个、第四个字符,最终生成的排列自然就缺少了包含第二个字符的所有组合。
修复方案:给循环变量添加块级作用域
只需要把所有循环变量用let声明(let会创建块级作用域,每个循环的变量都是独立的,不会互相干扰),代码就能正常工作了:
function perm(str){ function addNew(arr,char){ var result =[]; // 用let声明块级作用域的i for(let i=0;i<=arr.length;i++){ var temp =[...arr]; temp.splice(i,0,char); result.push(temp); } return result; } var chars =str.split(""); var results =[[]]; // 用let声明块级作用域的i for(let i=0;i<chars.length;i++){ var temp =[...results]; results =[]; // 用let声明块级作用域的j for(let j=0;j<temp.length;j++){ results =[...results,...addNew(temp[j],chars[i])]; } } return results; }
现在调用perm("abcd")就能得到所有24个完整的排列了~
内容的提问来源于stack exchange,提问作者pc12
相关产品推荐
相关产品推荐

