for\for of\for in\forEach\map\while\do while\some\filter\的性能對比

循環(huán)在我們的工作當(dāng)中是非常頻繁使用的,每個循環(huán)應(yīng)用的場景和適用的范圍都有一些區(qū)別,如果只是單純的比較哪個好哪個不好,應(yīng)該是沒有結(jié)果的,我這里做的性能對比,僅僅從循環(huán)讀取數(shù)值上的區(qū)別。主要包括:

  • for
  • for of
  • for in
  • forEach
  • map
  • while
  • do while
  • some
  • filter

這里使用webWork跑測試?yán)?

    var worker = new Worker('work.js');
    worker.postMessage("message");
    this.addEventListener('message', function (e) {
        let array = []

        function initData() {
          for (let i = 0; i < 1000000; i++) {
            array.push(i)
          }
        }
        initData()
        console.log(array)
    })
function testFunction(array) {

    function testFor() {
        let newArray = []
        console.time('testFor')
        for (let i = 0; i < array.length; i++) {
            newArray.push(array[i])
        }
        console.timeEnd('testFor')
    }
    testFor()

    function testForLen() {
        let newArray = []
        console.time('testForLen')
        for (let i = 0, len = array.length; i < len; i++) {
            newArray.push(array[i])
        }
        console.timeEnd('testForLen')
    }
    testForLen()

    function testForIn() {
        let newArray = []
        console.time('testForIn')
        for (let i in array) {
            newArray.push(array[i])
        }
        console.timeEnd('testForIn')
    }
    testForIn()

    function testForOf() {
        let newArray = []
        console.time('testForOf')
        for (let i of array) {
            newArray.push(array[i])
        }
        console.timeEnd('testForOf')
    }
    testForOf()

    function testWhile() {
        let newArray = []
        console.time('testWhile')
        let i = 0
        while (i < array.length) {
            newArray.push(array[i])
            i++
        }
        console.timeEnd('testWhile')
    }
    testWhile()

    function testDoWhile() {
        let newArray = []
        console.time('testDoWhile')
        let i = 0
        do {
            newArray.push(array[i])
            i++
        } while (i < array.length);
        console.timeEnd('testDoWhile')
    }
    testDoWhile()

    function testMap() {
        let newArray = []
        console.time('testMap')
        array.map((item) => {
            newArray.push(item)
        })
        console.timeEnd('testMap')
    }
    testMap()

    function testForeach() {
        let newArray = []
        console.time('testForeach')
        array.forEach((item) => {
            newArray.push(item)
        })
        console.timeEnd('testForeach')
    }
    testForeach()

    function testFilter() {
        let newArray = []
        console.time('testFilter')
        array.filter((item) => {
            newArray.push(item)
        })
        console.timeEnd('testFilter')
    }
    testFilter()

    function testSome() {
        let newArray = []
        console.time('testSome')
        array.some((item) => {
            newArray.push(item)
        })
        console.timeEnd('testSome')
    }
    testSome()

    function testReduce() {
        let newArray = []
        console.time('testReduce')
        array.reduce((all, a) => {
            newArray.push(a)
        }, 0)
        console.timeEnd('testReduce')
    }
    testReduce()
}

1000000數(shù)據(jù)量測試

單位ms

5000000數(shù)據(jù)量測試

單位ms

10000000數(shù)據(jù)量測試

單位ms

20000000數(shù)據(jù)量測試

單位ms

測試環(huán)境

  • CPU I7 7700K
  • 內(nèi)存 16G 3200HZ
  • 谷歌瀏覽器 80.0.3987.162(正式版本) (32 位)
  • 系統(tǒng)win10專業(yè)版 64位

經(jīng)過上面的四輪對比:

  • 性能最強(qiáng)的是while,不管數(shù)據(jù)量的大小,一直穩(wěn)居第一
  • 次之的do whilefor、for緩存length 三者性能差距并不大,在數(shù)據(jù)量低于2千萬級別時:do while > for > for緩存length,上了兩千萬后:for緩存length > do while > for
  • 第三梯隊的forEach、filter、somereduce幾乎性能相當(dāng),只有filter一直是第五,其他三者輪流換位置:filter > forEachsomereduce
  • 第四梯隊的map、for of,兩者在數(shù)據(jù)量較低差距還是挺大的,當(dāng)數(shù)據(jù)量上了2000W,性能差距就沒那么大了:map > for of
  • 性能最差的就是for in,基本上是最快的幾十倍的性能差距。

結(jié)果

while > do whileforfor緩存length > filter > forEachsomereduce > map > for of > for in;
結(jié)果不代表這些循環(huán)方法的真實最終效果,只能代表在我的電腦上,這些方法測試讀取數(shù)組數(shù)據(jù)之間的差異,for of for in 更擅長對象,至于真實的效果就不太敢定論了,但是對于一般的循環(huán) for循環(huán)的性能肯定是非常好的,所以能夠用for循環(huán)就不要用map、forEach等遍歷方式,當(dāng)然如果真的對于性能要求并不那么高的項目,用什么的區(qū)別也不太大,畢竟在百萬級別的數(shù)據(jù)讀取差異上,時間差距也在幾十ms上,只是對于復(fù)雜大量數(shù)據(jù)上,就要多多注意,另外僅僅在for循環(huán)上,書寫方式的差異也有性能的差異。我自己也封裝過一個方法,包裹for循環(huán)使它能夠像forEach一樣的書寫方式,提高效率的同時也不影響性能。

         /**
         * 遍歷工具,dataset可以是數(shù)組和對象 
         * 回調(diào)函數(shù) handler( item, index|key, dataset)
         * break----用return false
         * continue --用return ture
         * @param   {Object | Array}        dataset                    對象或者數(shù)組
         * @param   {Function}              handler                    回調(diào)函數(shù)
         * @param   {Context}               context                    上下文this
         * @return  {Array}                                            返回對象或數(shù)組
         */
        function each(dataset, handler, context) {
            let callback = 'undefined' === typeof context ? handler : function (value, index, collection) {
                return handler.call(context, value, index, collection);
            };
            let i, len, res;
            if (dataset instanceof Array) { //數(shù)組
                i = 0;
                len = dataset.length;
                for (; i < len; i++) {
                    res = callback(dataset[i], i, dataset);
                    if (false === res) {
                        break;
                    } else if (true === res) {
                        continue;
                    }
                }
            } else { //鍵值對象
                let keys = getkeys(dataset);
                i = 0;
                len = keys.length;
                for (; i < len; i++) {
                    res = callback(dataset[keys[i]], keys[i], dataset);
                    if (false === res) {
                        break;
                    } else if (true === res) {
                        continue;
                    }
                }
            }
            /**
             * 獲取對象自有屬性名
             * @param   {any}       obj              對象
             * @return  {Array}                      返回對象key數(shù)組
             */
            function getkeys(obj) {
                if (Object.prototype.toString.call(obj).slice(8, -1) !== 'Object') {
                    return [];
                }
                if (Object.keys) {
                    return Object.keys(obj);
                }
            }
            return dataset;
        }

示例

        let object1 = {
            ke: 1,
            ke2: 2,
            ke3: 3,
            ke4: 5
        }
        each(object1, (item, key) => {
            console.log(item)
        })

        let array = [1, 2, 3, 4, 5, 6, 7]
        each(array, (item, key) => {
            console.log(item)
        })
        let array = [1, 2, 3, 4, 5, 6, 7]
        each(array, (item, key) => {
            if(item>5){
              return false                //終止循環(huán)
            }
            console.log(item)
        })
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容