1. ホーム
  2. javascript

[解決済み] 無名関数の使用はパフォーマンスに影響しますか?

2023-03-02 19:30:38

質問

Javascriptで名前付き関数と匿名関数を使用した場合、パフォーマンスに違いがあるのでしょうか?

for (var i = 0; i < 1000; ++i) {
    myObjects[i].onMyEvent = function() {
        // do something
    };
}

function myEventHandler() {
    // do something
}

for (var i = 0; i < 1000; ++i) {
    myObjects[i].onMyEvent = myEventHandler;
}

前者はめったに使わない関数でコードを散らかさないのですっきりしていますが、その関数を何度も宣言していることは問題でしょうか?

どのように解決するのですか?

ここでのパフォーマンスの問題は、ループの各反復で新しい関数オブジェクトを作成するコストであり、無名関数を使用しているという事実ではありません。

for (var i = 0; i < 1000; ++i) {    
    myObjects[i].onMyEvent = function() {
        // do something    
    };
}

同じコード本体を持っていて、レキシカルスコープへのバインディングがないにもかかわらず、千差万別の関数オブジェクトを作り出している ( 閉鎖 ). 一方、次のものは単に と同じ 関数の参照をループ中の配列要素に代入しているからです。

function myEventHandler() {
    // do something
}

for (var i = 0; i < 1000; ++i) {
    myObjects[i].onMyEvent = myEventHandler;
}

ループに入る前に無名関数を作成し、ループ内で配列要素にその参照を代入するだけであれば、名前付き関数のバージョンと比較して、パフォーマンスや意味上の違いは全くないことがわかります。

var handler = function() {
    // do something    
};
for (var i = 0; i < 1000; ++i) {    
    myObjects[i].onMyEvent = handler;
}

要するに、名前付き関数より匿名関数を使うことに、観察可能なパフォーマンスコストはありません。

余談ですが、上記の内容からすると、「名前付き関数」と「匿名関数」の間に違いはないように見えるかもしれません。

function myEventHandler() { /* ... */ }

とする。

var myEventHandler = function() { /* ... */ }

前者は 関数宣言 であるのに対し、後者は無名関数への変数代入です。両者は同じように見えるかもしれませんが、JavaScriptは両者を若干異なるものとして扱います。この違いを理解するためには、" JavaScript の関数宣言のあいまいさ ".

どのようなアプローチであっても、実際の実行時間は、ブラウザのコンパイラとランタイムの実装によって大きく左右されます。最近のブラウザのパフォーマンスの完全な比較については、以下を参照してください。 JS Perf サイト