为什么这个调用简单的辅助函数会导致无限循环?

时间:2016-08-01 10:33:37

标签: javascript for-loop global-variables infinite-loop helpers

我一直在调试这几个小时无济于事。

以下代码检查一系列数字中的每个数字是否没有重复数字(111应该返回false; 123应该返回true)并返回一个数组系列中所有不包含重复数字的数字。

对于数组中的每个值,数组应填充辅助函数返回的值true,但运行noRepeats()会导致无限循环或长数组1。造成这种情况的原因是什么?

// DO NOT RUN AS IS; POTENTIAL INFINITE LOOP

var noRepeatDigits = function (n) {
  n = n.toString();
  for ( i = 0 ; i < n.length ; i ++ ) {
    for ( j = i + 1 ; j < n.length ; j ++ ) {
      if ( n.charAt(i) === n.charAt(j) ) {
        return false;
      }
    }
  }
  return true;
};

console.log( noRepeatDigits(113) ); // false
console.log( noRepeatDigits(123) ); // true

var noRepeats = function (n1, n2) {
  var arr = [];
  for ( i = n1 ; i <= n2 ; i ++ ) {
    if ( noRepeatDigits(i) ) {
      arr.push(i);
    }
  }
  return arr;
};

console.log( noRepeats(1, 100) );

2 个答案:

答案 0 :(得分:4)

你忘了var i,所以迭代器是全局的,使用它的两个函数互相覆盖。这最多会导致意外行为,最糟糕的是无限循环。

但是,您可以大量简化noRepeatDigits功能:

noRepeatDigits = function(n) {
    return !n.toString().match(/(.).*?\1/);
};

这有效地完成了原始功能所做的工作,但将繁重的工作卸载到内置的低级功能,通常说速度要快得多。

答案 1 :(得分:2)

这是Niet the Dark Absol答案的补充。

正如他所指出的,意外行为是由循环中使用的变量引起的。我建议你将"use strict";提示放在Javascript的顶部。这样你就不会再犯同样的错误了。

示例:

"use strict";
// DO NOT RUN AS IS; POTENTIAL INFINITE LOOP

var noRepeatDigits = function (n) {
    n = n.toString();
    for ( i = 0 ; i < n.length ; i ++ ) {
        for ( var j = i + 1 ; j < n.length ; j ++ ) {
            if ( n.charAt(i) === n.charAt(j) ) {
                return false;
            }
        }
    }
    return true;
};

<强>引用: 将错误转换为错误

  

严格模式会将之前接受的一些错误更改为错误。   JavaScript旨在为新手开发人员提供便利,并且   有时它会给出错误无误的操作   语义。有时这可以解决当前的问题,但有时候   这会在未来造成更严重的问题。严格模式对待这些   将错误视为错误,以便发现并及时修复。

     

首先,严格模式使得无法意外创建全局   变量。在正常的JavaScript中错误输入赋值中的变量   在全局对象上创建一个新属性并继续“工作”   (虽然未来的失败是可能的:可能,在现代JavaScript中)。   意外创建全局变量的赋值   扔严格模式:

查看:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode