2016-09-10 34 views
2

在函數內部定義函數或在類範圍中定義函數之間是否存在性能差異?渲染函數內部函數表達式的性能

render功能範圍:

render() { 
    const renderItem = (item) => (<li>{item.name}</li>); 

    return (<ul> 
    {this.props.itemList.map((item) => renderItem(item))} 
    </ul>); 
} 

class範圍:

export default class MyComponent extends React.Component { 
    const renderItem = (item) => (<li>{item.name}</li>); 

    render() { 
    return (<ul> 
     {this.props.itemList.map((item) => this.renderItem(item))} 
    </ul>); 
    } 

} 
+0

在這兩種情況下,您都不需要製作一個新的包裝函數來調用'renderItem()';你可以直接傳遞一個對函數的引用。 – Pointy

+0

是的,我知道,但這是一個簡單的例子。有時我需要將它包裝到一個看起來很乾淨的函數中,否則它看起來很雜亂。 – kosker

+0

我的意思是:'{this.props.itemList(renderItem)}'或'{this.props.itemList(this.renderItem)}'是等價的。性能差異是微不足道的。 – Pointy

回答

1

是的,不知何故,性能有所不同。

但是,這種差異是如此如此之小以至於你甚至可以注意到或告訴它們有什麼不同。

問題是,當您在render方法中定義renderItem時,每次調用render方法時,renderItem函數都將被重新創建。換句話說,renderItem在生活中只定義一次。

因此,您可以認爲「外部」方法會更快。但事情是,在「內部」方法中,renderItem將只在每個呼叫中​​創建一次。因此,例如,如果有100萬件物品需要渲染,整個過程的「瓶頸」將會是map本身,而不是renderItem方法的創建。

但是爲了測試,我建立了這個樣本,來測試這兩種方法,insideFunctionoutsideFunction。您可以複製並在瀏覽器中運行。

爲了測試,你可以運行bench(10000)看到這兩種方法將花費多少時間與10000元(在我的電腦的陣列,這種規模的平均時間大約爲0.05〜0.07秒。

你可以同時運行多個bench測試和看到輸出平均水平,:nBenchs(10, 10000),運行10個bench(10000)測試

結論:在我的電腦,100萬位運行與陣列測試中,我得到的東西圍繞7秒平均而言,這兩種方法。運行這幾次,在大多數情況下,「o utside「方法比」內部「快了一半。但請牢記這一點,如果您的代碼需要7秒才能將輸出返回給用戶,那麼您應該開始考慮以其他方式減少此值(如首先顯示結果的一部分並更快)。如果你正在構建一個處理這些數據的應用程序,並且擁有沉重的進程算法(這在網絡/反應應用程序中並不常見),那麼每一次爲你節省7%時間的動作(七秒鐘的半秒鐘內)案例)是寶貴的。

(function() { 
    function renderItem(text) { 
    let item = document.createElement('li'); 
    item.innerHTML = text; 

    return item; 
    } 
    function outsideFunction(array) { 
    return array.map(renderItem); 
    } 

    // exponse outsideFunction 
    window.outsideFunction = outsideFunction; 
})(); 

(function() { 
    function insideFunction(array) { 
    function renderItem(text) { 
     let item = document.createElement('li'); 
     item.innerHTML = text; 

     return item; 
    } 

    return array.map(renderItem); 
    } 

    // exponse insideFunction 
    window.insideFunction = insideFunction; 
})(); 

// just build an array with n elements 
function buildArray(n) { 
    let testArray = []; 
    for(let i=0; i<n; i++) { 
    testArray.push(`Text with index ${i}`); 
    } 

    return testArray; 
} 

// run nb test benchs with an array with n elements 
function nBenchs(nb, n) { 
    let Ocount = 0, Icount = 0; 
    let result; 

    for(let i=0; i<nb; i++) { 
    result = bench(n); 

    Ocount += result.Oend; 
    Icount += result.Iend; 
    } 

    // output the average 
    console.log(`outsideFunction average: ${Ocount/(nb*1000)} seconds`); 
    console.log(`insideFunction average: ${Icount/(nb*1000)} seconds`); 
} 

// run a test bench with an array with n elements 
function bench(n) { 
    n = n || 100; 

    let testArray = buildArray(n); 
    let start, Oend, Iend; 

    start = new Date(); 
    outsideFunction(testArray); 
    Oend = ((new Date())-start); 

    console.log(`outsideFunction: ${Oend/1000} secods`); 

    start = new Date(); 
    insideFunction(testArray); 
    Iend = ((new Date())-start); 

    console.log(`insideFunction: ${Iend/1000} secods`); 

    return { Oend, Iend }; 
} 
0

在類範圍的定義這將是稍快,因爲該功能將只產生一次。如果你在render-method中定義它,每次調用render-method時都會創建函數。

也就是說,它不太可能會有明顯的影響。