35101


こんにちは。  
一般的なJavaScriptのWebサイトでは、この手のテクニックがみつからず、検索しようにも検索ワードも特定できないので、ご質問します。

ベンチマーク関数などで、以下のように動かしたいのですが、記述方法がわかりません。  
疑似コードです

[code]

    var benchMark = function (loopCount, f, args1, args2, args3 …) {
      for … loopCount {
        f(args1, args2, args3…)
      }
    }
    
[/code]

ベンチマーク関数の呼び出し時に、関数fとその引数をわたして、  
ベンチマーク関数の内部で、関数fに引数を渡して実行させたいのです。  
fに対しては、任意個数の引数をわたしたいです。

もちろん、引数なしのものでしたら簡単でした。  
サンプルコードをのせておきます。HTMLです。

やり方をご存知な方おられましたら、教えてください。  
あるいは、無理、という情報や、参考になるページを教えていただくだけでも

[code]

    <!DOCTYPE html>
    <html lang="ja">
      <head>
        <meta charset="utf-8">
        <title></title>
    <script>
    
      var benchMark = function (loopCount, f, args) {
        var
          i, max, 
          startTime, endTime;
        startTime = new Date();
        for (var i = 1, max = loopCount - 1; i <= max; i+=1) {
          f();
        }
        endTime = new Date();
        return endTime - startTime;
      };
    
      var test1 = function () {
        return '';
      };
      console.log(benchMark(1000000, test1));
      console.log('test finish');
    
    </script>
      </head>
    <body>
    </body>
    </html>
    
[/code]


CC BY-SA 3.0
2017-05-28T11:23:04.720
35092
2017-05-29T03:00:04.477
21047
question
javascript
JavaScript ベンチマーク関数などで実行する関数と引数を渡して動作させたい


オーバーヘッドとかは無視してますが、ES2015ならこのように書けます。

[code]

    function bench (times, func, ...args) {
      const startTime = new Date();
      for(let i=0;i<times;i++) {
        func(...args);
      }
      const endTime = new Date();
      return endTime - startTime;
    
    }
    
    const test1 = function (arg) {
      return arg;
    };
    
    console.log(bench(1000000, test1, 'arg1'));
    console.log('test finish');
[/code]

もしES2015に非対応の古いブラウザ等も考慮する必要がある場合は[babel](http://babeljs.io/repl/#?babili=false&evaluate=true&lineWrap=true&presets=es2015&targets=&browsers=&builtIns=false&debug=false&code=function%20bench%20\(times%2C%20func%2C%20...args\)%20%7B%0A%20%20const%20startTime%20%3D%20new%20Date\(\)%3B%0A%20%20for\(let%20i%3D0%3Bi%3Ctimes%3Bi%2B%2B\)%20%7B%0A%20%20%20%20func\(...args\)%3B%0A%20%20%7D%0A%20%20const%20endTime%20%3D%20new%20Date\(\)%3B%0A%20%20return%20endTime%20-%20startTime%3B%0A%0A%7D%0A%0Avar%20test1%20%3D%20function%20\(arg\)%20%7B%0A%20%20return%20arg%3B%0A%7D%3B%0A%0Aconsole.log\(bench\(1000000%2C%20test1%2C%20'arg1'\)\)%3B%0Aconsole.log\('test%20finish'\)%3B%0A)とかを参考にしてみてください


CC BY-SA 3.0
2017-05-28T11:35:48.980
35094
2017-05-28T11:57:22.113
2017-05-28T11:57:22.113
2376
2376
35092
answer


`args`
が配列（の形で実行する関数の引数を渡す）なら[apply](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/apply)
を使って`f.apply(null, args);` のように実行できます。

[code]

    function expression2(x, a, b, c){
      console.log(x*(a*x + b) + c);//動作確認のため
      return a*x*x + b*x + c;
    }
    
    function benchMark(loopCount, f, args) {
      //while(loopCount--) {
        f.apply(null, args);
      //}
    }
    
    benchMark(1000000, expression2, [1,2,3,4]);
[/code]

普通に引数の並びとして書く場合、[arguments](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions_and_function_scope/arguments)変数と[slice](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/slice)を使って配列に変換します。

[code]

    function expression2(x, a, b, c){
      console.log(x*(a*x + b) + c);//動作確認のため
      return a*x*x + b*x + c;
    }
    function expression1(x, a, b){
      console.log(a*x + b);//動作確認のため
      return a*x + b;
    }
    
    function benchMark(loopCount, f) {
      //loopCount と f は含めないようにsliceして配列を作る。
      var args = [].slice.call(arguments, 2)
      //関数の呼び出し以外は省略
      f.apply(null, args);
    }
    
    benchMark(1000000, expression2, 2,1,2,3);
    benchMark(1000000, expression1, 5,4,6);
[/code]


CC BY-SA 3.0
2017-05-29T02:50:54.950
35101
2017-05-29T03:00:04.477
2017-05-29T03:00:04.477
5044
5044
35092
answer