如果将JS循环体中用到的变量都在循环体外部进行声明,并对自定义类型进行了初始化,这样做是否性能更好,针对此疑问在Chrome浏览器中进行测试。

测试

测试环境为chrome,测试情况分为三种,如下:

  1. 变量声明位于循环体内部
  2. 变量声明位于循环体外部,但未初始化
  3. 变量声明位于循环体外部,并初始化

对不同数据类型进行测试,包括:

累计测试100次,统计总耗时(单位:ms),测试结果如下表:

数据类型 情况1 情况2 情况3 备注
数字 19732 19153 19273 每次循环10000000次
布尔型 32625 33660 32821 每次循环10000000次
字符串 33739 33835 33617 每次循环10000000次
THREE.Vector3 42423 42281 15624 每次循环1000000次
THREE.Spherical 35679 36249 15971 每次循环1000000次

结论

  1. 对于全部数据类型,情况2与情况1相比,代价一致,不会有性能的提升
  2. 对于JS基本类型,三种情况代价一致,chrome应该对其进行了优化,因此建议将JS基本类型变量声明放到循环体内部,程序更加易读
  3. 对于自定义类型,情况3与前两种情况相比,代价不到一半,性能有明显提升,因此建议将自定义类型声明及初始化放到循环体外部

代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>测试for循环中的变量声明不同代价</title>
</head>
<body>
<h1>测试for循环中变量声明处于不同位置时的相应代价</h1>

<script src="../static/lib/three.js/r85/three.js"></script>
</body>
</html>
<script>
    // 循环次数
    var n = 1000000

    // 获取时间戳
    function get_time_stamp() {
        return (new Date()).valueOf();
    }

    // 1. 变量声明在循环体内部
    function test1() {
        var result1 = []
        var ts1_start = get_time_stamp()
        for (var i = 0; i < n; i++) {
            var t1 = new THREE.Spherical();
            t1.set(i, Math.PI, Math.PI)
            result1.push(t1)
        }
        var ts1_end = get_time_stamp()
        var ts1 = ts1_end - ts1_start
        console.log(ts1)

        return ts1
    }

    // 2. 变量声明在循环体外部,但未初始化
    function test2() {
        var result2 = []
        var ts2_start = get_time_stamp()
        var t2
        for (var i = 0; i < n; i++) {
            t2 = new THREE.Spherical();
            t2.set(i, Math.PI, Math.PI)
            result2.push(t2)
        }
        var ts2_end = get_time_stamp()
        var ts2 = ts2_end - ts2_start
        console.log(ts2)

        return ts2
    }

    // 3. 变量声明在循环体外部,并初始化
    function test3() {
        var result3 = []
        var ts3_start = get_time_stamp()
        var t3 = new THREE.Spherical();
        for (var i = 0; i < n; i++) {
            t3.set(i, Math.PI, Math.PI)
            result3.push(t3)
        }
        var ts3_end = get_time_stamp()
        var ts3 = ts3_end - ts3_start
        console.log(ts3)

        return ts3
    }

    // 测试100次,取总时间
    var total = 0
    for (var i = 0; i < 100; i++) {
        var t = test3()
        total += t
    }
    console.log("累计用时", total)

</script>