2

我在一個反應​​應用程序中有一段時間相當有限的代碼,它可以在窗體中的所有用戶按鍵上運行。它一般沒有性能問題,但我正在考慮優化它,並且在for (let k in obj)Object.keys(obj).reduce之間的performance differences有點驚訝。我認爲在JS中設置函數調用堆棧等將會很昂貴,但以下例程的功能版本會將程序中的一個從水中排出(整個數量級!)。程序與功能性Javascript

這裏有不同的版本:

程序

const generateProps = (fields, source, start) => { 
 
    if (!fields) return start 
 
    let finish = {...start} 
 
    for (let k of Object.keys(fields)) { 
 
    const fld = fields[k] 
 
    if (fld instanceof Array) { 
 
     if (fld.length === 0) continue 
 
     // Handle an array of scalars (e.g. phoneNumbers) 
 
     if (fld[0].hasOwnProperty('value')) { 
 
     let sf = {} 
 
     for (let i = 0; i < fld.length; i++) { 
 
      sf[i] = fld[i] 
 
     } 
 
     finish = generateProps(sf, source[k], finish) 
 
     // Handle an array of fields (e.g. addresses) 
 
     } else { 
 
     for (let i = 0; i < fld.length; i++) { 
 
      finish = generateProps(fld[i], source[k][i], finish) 
 
     } 
 
     } 
 
    } else { 
 
     finish = { 
 
     hasError: fields[k].hasError || fields[k].value === '' || finish.hasError, 
 
     isEditing: fields[k].editing || finish.isEditing, 
 
     unchanged: (!fields[k].isNew && fields[k].value === source[k]) && finish.unchanged, 
 
     hasNew: fields[k].isNew || finish.hasNew 
 
     } 
 
    } 
 
    } 
 
    return finish 
 
}

功能

const generateProps = (fields, source, start) => { 
 
    if (!fields) return start 
 
    const keys = Object.keys(fields) 
 
    return keys.reduce((props, k) => { 
 
    const fld = fields[k] 
 
    if (fld instanceof Array) { 
 
     if (fld.length === 0) return props 
 
     // Handle an array of scalars (e.g. phoneNumbers) 
 
     if (fld[0].hasOwnProperty('value')) return generateProps(fld.reduce((sf, f, i) => {sf[i] = f; return sf}, {}), source[k], props) 
 
     // Handle an array of fields (e.g. addresses) 
 
     return fld.reduce((subp, f, i) => generateProps(f, source[k][i], subp), props) 
 
    } 
 
    return { 
 
     hasError: fields[k].hasError || fields[k].value === '' || props.hasError, 
 
     isEditing: fields[k].editing || props.isEditing, 
 
     unchanged: (!fields[k].isNew && fields[k].value === source[k]) && props.unchanged, 
 
     hasNew: fields[k].isNew || props.hasNew 
 
    } 
 
    }, start) 
 
}

這裏是jperf results

正如你可以看到,當你運行測試,程序版本比功能更慢了近50%。我有興趣聽到爲什麼會出現如此明顯的差異。

+1

正如你經常那樣,你鏈接的[基準](https://jsperf.com/for-in-vs-for-of-keys-vs-keys-reduce)是完全有缺陷的。 – Bergi

+0

除了有缺陷之外,'for(let ... in ...)'的運行速度比firefox ....中的最後兩個快兩倍,Object.keys(obj).reduce'的運行速度比第一個快兩倍兩個在Chrome中 - 所以在一個瀏覽器上的基準測試意味着什麼:p –

+0

您使用的瀏覽器是什麼? '{... start}'是「程序性」jsperf中的語法錯誤。 – Bergi

回答

0

好的,我發現了一個關鍵的區別!功能版本是變異start(我曾假設減少將創建一個副本,來自ramdajs背景),而程序正在創建一個副本。如果我將最高reduce調用的最後一個參數更改爲{...start},則它們差不多。

這讓我想知道爲什麼對象傳播這個慢嗎?