2017-12-07 11 views
2

次のコードは、lodashのnegate関数のソースコードです。パラメータの長さが4未満の場合は、applyの代わりにswitch-caseを直接使用することがわかります。このコードについてどんな魔法?パフォーマンスが向上していますか?スプリットポイントが4の理由は?なぜlodashはネゲート機能でswitch-caseを使用しますか?

function negate(predicate) { 
    if (typeof predicate != 'function') { 
    throw new TypeError(FUNC_ERROR_TEXT); 
    } 
    return function() { 
    var args = arguments; 
    switch (args.length) { 
     case 0: return !predicate.call(this); 
     case 1: return !predicate.call(this, args[0]); 
     case 2: return !predicate.call(this, args[0], args[1]); 
     case 3: return !predicate.call(this, args[0], args[1], args[2]); 
    } 
    return !predicate.apply(this, args); 
    }; 
} 
+0

わかりませんが、 'switch'は' if..else'ラダーよりも優れています。プラス、少ないタイピング。 – Rajesh

+2

OPの質問は 'if..else'の代わりに' switch'を使う理由ではありません。問題はなぜ条件付きであるかということです。 – JanS

+0

スプリットポイントは4であると思います。なぜなら、oopで3つ以上のパラメータを取るような機能を持たないようにしなければならないからです(自分で繰り返すことができない限り、 。そしておそらくベンチマークもしたでしょう。 'apply'は' call'メソッドより遅いでしょう。 –

答えて

0

でも、私のクリスタルボールはまだ修理中です。ですから、著者の意図について私はあなたに最高の推測しかできません。

ここでのポイントは、switchについてではなく、オプティマイザがこの全体のコンストラクトをこれらのパスの単一のものに変換できるようにすることです。この場合、関数は一貫した引数のセットで呼び出されると仮定します。

この全体を基本的に最適化し、predicateの関数本体をこの疑似コードのようなものにインライン化することさえできます。機能を想定し
は常に2つの引数

function(){ 
    //a gate to ensure the optimization is still correct/applicable 
    //probably more complex than this 
    if(arguments.length === 2){   
     //assign predicate function args 
     var value = arguments[0], index = arguments[1]; 
     [function body of predicate] 
    }else{ 
     [de-optimize] 
     //execute the de-optimized version of this function 
    } 
} 

なぜ0..3引数で呼び出されたのですか?これらは最も一般的なケースです。そして、デフォルトのケースは完全性のためだけに存在し、(まったく、私の意見)決して/決して襲われるべきではありません。

もう一つのポイントは、Function#call()が私の経験ではFunction#apply()より少し早いかもしれません。まれにそれについて考えることさえありますが、これは他のライブラリで使用されるライブラリなので、すべてのパフォーマンスの問題が指数関数的に増加する可能性があります。

関連する問題