简体   繁体   中英

Why is this call to a simple helper function causing an infinite loop?

I've been debugging this for hours to no avail.

The following code checks whether each number in a series of numbers has no repeating digits ( 111 should return false ; 123 should return true ) and return an array of all numbers in the series which contain no repeating digits.

The array should be populating with values which the helper function returns as true for each value in the array, but running noRepeats() causes an infinite loop or a long array of 1s. What is causing this?

 // 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) ); 

You forgot to var i , so the iterator is global and the two functions using it overwrite each other. This causes unexpected behaviour at best, an infinite loop at worst.

However you can simplify your noRepeatDigits function a lot:

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

This effectively does what your original function did, but offloads the heavy work to built-in, lower-level functions which generally speaking are significantly faster.

This is an addon to Niet the Dark Absol's answer.

As pointed out by him the unexpected behavior was caused by the variables used in your loop. I would recommend you to put the "use strict"; hint at the top of your Javascript. That way you will not make the same kind of mistake again.

Example:

"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;
};

Quote: Converting mistakes into errors

Strict mode changes some previously-accepted mistakes into errors. JavaScript was designed to be easy for novice developers, and sometimes it gives operations which should be errors non-error semantics. Sometimes this fixes the immediate problem, but sometimes this creates worse problems in the future. Strict mode treats these mistakes as errors so that they're discovered and promptly fixed.

First, strict mode makes it impossible to accidentally create global variables. In normal JavaScript mistyping a variable in an assignment creates a new property on the global object and continues to "work" (although future failure is possible: likely, in modern JavaScript). Assignments which would accidentally create global variables instead throw in strict mode:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM