JavaScript中冒泡排序,同样的写法,为什么封装在函数中会出现死循环,而没有封装的不会出现。

下面两端代码:
1.函数封装的冒泡排序

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title></title>
    <link rel="stylesheet" href="">
    <script type="text/javascript">
        var arr1 = sort([2,3,4,9,7]);
        function sort(arr) {
            for (var i = 0; i < arr.length - 1; i++) {
                for (var j = 0; j < arr.length - i - 1; j++) {
                    if (arr[j] > arr[j + 1]) {}
                    var temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
            return arr;
        }
        console.log(arr1);
    </script>
</head>
<body>
    
</body>
</html>

这段代码执行是没有问题的。

2.没有封装成函数的冒泡排序

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title></title>
    <link rel="stylesheet" href="">
    <script type="text/javascript">
        var arr = [2,3,4,9,7];
        for (var i = 0; i <= arr.length - 1; i++) {
            for (var j = 0; j <= arr.length - i - 1; j++) {
                if (arr[j] > arr[j + 1]) {
                    var temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j+ 1] = temp;
                }
            }
        }
        console.log(arr);
    </script>
</head>
<body>
    
</body>
</html>

这段代码运行也没有问题。

注:两端代码的循环条件有区别。(j <arr.length 和 j <= arr.length)

问题来了

我在下面的代码中会出现死循环,为什么我在2中的代码不会出现死循环?(我把函数中的循环 j < arr.length改为了 j <= arr.length)

注:已经知道为什么出现死循环,就是想知道同样的写法,为什么没有封装的不会出现死循环。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title></title>
    <link rel="stylesheet" href="">
    <script type="text/javascript">
        var arr1 = sort([2,3,4,9,7]);
        function sort(arr) {
            for (var i = 0; i <= arr.length - 1; i++) {
                for (var j = 0; j <= arr.length - i - 1; j++) {
                    if (arr[j] > arr[j + 1]) {}
                    var temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
            return arr;
        }
        console.log(arr1);
    </script>
</head>
<body>
    
</body>
</html>

image

阅读 2.2k
3 个回答
        var arr1 = sort([2,3,4,9,7]);
        function sort(arr) {
            for (var i = 0; i <= arr.length - 1; i++) {
                for (var j = 0; j <= arr.length - i - 1; j++) {
                    if (arr[j] > arr[j + 1]) {}
                    var temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
            return arr;
        }

有等号,j 就可以等于arr.length - 1(当 i==0 的时候)。此时,arr[j+1] 不在数组范围内,已经越界了。其值应该是 undefined

undefined 做比较,一定是 false 。这样你的 2 里的交换不会执行。但是 1 跟 3 的交换是这样的:

                    if (arr[j] > arr[j + 1]) {}
                    //                        ^  这是为什么 ....

它实际不受 if 控制(这是错的,改改吧 ... )。

于是 arr[j+1]=temp 一定会执行,执行以后,数组变长了。

于是内层循环每执行一次数值长度增加一,j 也每此增加一,于是 j <= arr.length - i -i 总是是 true

  var arr = sort([2, 3, 4, 9, 7]);
  
    function sort(arr) {
        for (var i = 0; i <= arr.length - 1; i++) {
   
            for (var j = 0; j <= arr.length - i - 1; j++) {

                if (arr[j] > arr[j + 1]) {
                    var temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
        return arr;
    }

    console.log(arr);

if (arr[j] > arr[j + 1]) {},写外面造成内部for死循环,因为arr的长度一直在增加

很关键的一点,JS数组越界赋值会自动给数组扩容。

let arr = [1]
arr[5] = 1
console.log(arr.length) // 输出6

上述3段代码中后2段都存在越界访问(访问不会扩容,不同于赋值),但二段和三段内层循环的if语句不相同。三段的内层循环最后一次遍历都会导致越界赋值(if没用),而二段则不会,因为任意数字和越界访问的undefined比较都返回false,if条件不成立。

推荐问题
宣传栏