これは
YASSの基礎となる実用的な方法の分析に専念するシリーズの3番目の記事です。 最初の記事は
モジュール構造についてであり、2番目
はCSSセレクターを選択してループを組織する論理についてでした。
条件分岐
分岐のロジックの最も明白なコンポーネントから始めましょう。 どのアルゴリズムでも、チェックされる条件に応じて、1つまたは別の継続を選択する必要がある場所があります。 次の例を見てみましょう。 最初のケースでは、3つの単純なネストされたチェックがあります。
var a = 1
b = 2
c = 3;
if(a == 1){
if(b == 2){
if(c == 3){
...
}
}
}
最も興味深いのは、次の
if組み合わせた
ifと同じくらい高速
if :
if(a == 1 && b == 2 && c == 3){
...
}
ただし、後者はわずかに小さくなります。 目標が最小コードサイズではない場合、読みやすさを向上させるには、最初のオプションを使用する必要があります。 すべてを最小化する
if-then-else 、
if-then-else式の使用を検討でき
if-then-else 。 ただし、このような構造のパフォーマンスは次の点に留意する必要があります。
var v = a == 1? b == 2? c == 3? 1:0:0:0;
通常の分岐よりも約10〜50%少なく、少し高いと考えられます。
すべての変数が数値である場合、指定された合計の等値のチェックは5〜10%高速に実行されます。
if(a + b + c == 6){
...
}
変数の存在とその非負性(つまり、変数が
undefinedではない、
NaN 、
null 、
'' 、0ではない)だけをチェックする必要がある場合、次のオプションは5-10%高速に動作します。前のケースよりも(および最初の例よりも10〜20%高速):
if(a && b && c){
...
}
多くの場合、単なる数字よりも複雑なものをチェックする必要があります。 たとえば、指定された1つ以上のオブジェクトと文字列が一致します。 この場合、次の比較が必要です。
var a = 1
b = 2
c = '3';
if(a == 1 && b == 2 && c === '3'){
...
}
ここでは、
===をキャストせずに比較を使用します。これは、非数値変数の場合、通常の比較よりも10〜20%高速です。
行選択
多くの場合、特定の行に基づいて条件分岐の1つを選択する必要があります。 通常、これには
RegExpオブジェクトのメソッド(
exec 、
test )または文字列メソッド(
match 、
search 、
indexOf )が使用されます。 文字列が何らかの正規表現に一致するかどうかを確認する必要がある場合
test 、
test最良の
testです。
var str = 'abc'、
regexp = new RegExp( 'abc');
if(regexp.test(str)){
...
}
このような設計は、同様の
execよりも40%高速に動作します。
if(regexp.exec(str)[1]){
...
}
文字列メソッドの
match 、作成された
RegExpオブジェクトの
execメソッドに似ていますが、単純な式では10〜15%高速に動作します。 ただし、
searchメソッドは
testよりも少し遅く(5〜10%)動作します。これは、後者が見つかった部分文字列を返さないためです。
「1回」正規表現が必要な場合は、より高速な(新しいオブジェクトの初期化オプションに比べて約10%の)レコードが適しています。
if(/abc/.test(str)){
...
}
最後に、部分文字列が指定された文字列にあるかどうかを確認する必要がある場合、
indexOfは議論の余地のないリーダーになり、正規表現の解析よりも2倍速く動作します。
if(str.indexOf( 'abc')!= -1){
...
}
完全一致とハッシュ
次の正規表現を考えてみましょう:
/a|b|c/ 。 この場合、指定された行で可能なオプションの1つ(またはこのオプションと文字列の等価性)の存在を確認する必要があります。 完全一致の場合、正規表現よりも高速(50%)で、文字列がハッシュのキーとしてチェックされます。
var hash = {'a':1、 'b':1}、
str = 'a';
if(h [str]){
...
}
このようなハッシュの高速化(20%)は、特定の値の文字列の正確なチェックのみになります。
if(str === 'a' || str === 'b'){
...
}
ネストされた
if 、対応する値に
switchてハッシュ内の値をチェックする3つの構成要素を検討する
if 、次の興味深い機能に注目する価値があります。 ネストの
ifレベルが少ない
if (値が数個しかない場合、または最初または2番目の値を非常に頻繁に終了する場合)、
ifおよび
switch構造はハッシュでパフォーマンスが約10%向上します。 多数の値があり、それらがすべてほぼ同じ確率である場合、一般的な場合のハッシュはすでに20%速くなっています。 これは、関数の呼び出しだけでなく、変数値の確立にも同様に適用されます。 つまり、関数呼び出しでブランチを作成するには、ハッシュを使用するのが最善です。
YASSに戻る。 CSSセレクターを分析するとき、いくつかのサブタスクを区別できます。これらのサブタスクは「選択問題」として説明されています。
- 単純な場合の分岐は、
test介して入力文字列をチェックすることにより行われます。
if(/^►\w[:#.[►\w\\\\\\\\\\\\!!*$/.test(selector)){
...
} else {
...
}
- 最も単純な場合の分岐(識別子またはクラスで選択する必要がある場合)。 合計5つの値があり、そのうちの3つは比較的同等の確率(クラス、識別子、またはタグによる選択)であるため、
switch使用されます。
switch(firstLetter){
ケース '#':
...
休憩;
ケース '。':
...
休憩;
ケース ':'
...
休憩;
ケース '[':
...
休憩;
デフォルト:
...
休憩;
}
- 正しい親子関係(
> 、 + 、 ~ )を選択するための完全に類似した画像を観察します:ここでも、 switchのみ:
スイッチ(祖先){
ケース '':
...
休憩;
ケース「〜」:
...
休憩;
ケース '+':
...
休憩;
ケース '>':
...
休憩;
}
- 最後に、子修飾子(
first-child 、 last-child 、 nth-childなど)の対応する検証関数の選択と、属性( ~= 、 *= 、 =など)の検証関数の選択が実行されますすでに特別なハッシュを介して:
_.attr = {'':...、 '=':...、 '&=':...、 '^ =':... ...}
要約表
文字列をチェックするさまざまな方法について少し要約すると、次のようなテーブルを作成できます。
| 挑戦する | ソリューションツール |
|---|
| 数値チェック | 通常の比較( == ) |
| 複数の数値の確認 | 金額の比較 |
| 数値がゼロでないことを確認するか、存在を確認します | 与えられた変数の否定をチェックする( ! ) |
| 文字列を解析し、パーツを配列に割り当てる | String.match(RegExp)またはRegExp.exec(String) |
| 正規表現の文字列を確認してください | RegExp.test(String) |
| サブストリングのストリングを確認してください | String.indexOf(String) |
| 文字列の正確な対応(または値セットの1つと一致)の確認 | キャストなしのif ( === ) |
| 正確な値に基づく選択(値1〜2) | 条件付きif構文 |
| 正確な値に基づく選択(値3〜8) | switch |
| 正確な値(8より大きい値)に基づく選択 | 値に一致するキーを持つハッシュ |
おそらく、この表にさらにいくつかのケースを追加するか
、JavaScriptでの単純な構造の
パフォーマンスに関する記事を参照して、適切な結論を引き出すことができます。
継続するには...