JavaScriptでJSONをモードマッチングする(Part 2-実現)

3872 ワード

Notify&Captureがnotifyとcaptureを実現するのはとても簡単です.captureから入ってきたhandlerを全部保存して、notifyの中にマッチするhandlerを見つけたらいいです.
 
  
var filterHandlerBundles = [];
Dispatch.capture = function(pattern, handler) {
var filter = createFilter(pattern);
filterHandlerBundles.push({
"filter": filter,
"handler": handler
});
};
Dispatcher.notify = function(json) {
for (var i = 0; i < filterHandlerBundles.length; i++) {
if (filterHandlerBundles[i].filter.apply(this, arguments)) {
filterHandlerBundles[i].handler(json);
}
}
};
このコードの論理がはっきりしています.鍵はクリアーFilterの部分です.この関数は、説明モードのJSONをJSONが一致するかどうかを判定する関数に変換するのを担当しています.
Operators
私たちは多くの演算法を設計しましたが、どうやって彼らを実現しますか?覚えてください.switch caseはいらないです.したがって、演算子と実装の間のマッピング関係を保存するために関連する配列を使用することができます.
 
  
var operators = {};
operators["lt"] = function(testValue, value) {
return arguments.length == 2 && value < testValue;
};
operators["lte"] = function(testValue, value) {
return arguments.length == 2 && value <= testValue;
};
operators["gt"] = function(testValue, value) {
return arguments.length == 2 && value > testValue;
};
operators["gte"] = function(testValue, value) {
return arguments.length == 2 && value >= testValue;
};
そうすると、私たちは「$」の後の演算子を抜き出しさえすれば、すぐに対応する判定関数を見つけることができます.上の4つは比較的演算子です.実現しやすいので、ここに置いて例を作ります.
比較的難しい関数はeqであり、データの種類に応じて具体的な判断を選択する必要があるからである.String、Number、Booleanに対してeqは==を意味します.Arayに対してeqという意味は中の各要素がeqであり、順番が一致しているということです.Objectについては、eqの意味は各サブ条件が一致するため、各サブ条件の演算子文字列を抽出し、対応する演算子を呼び出す必要がある.具体的には完全コードを参照できます.
他の演算子は簡単にできます.ここでは提示するだけで、これらの演算子のサブセットまたはサブセットは自分の実際のニーズに応じて設定できます.
in-配列を巡回して、少なくとも一つのeqが見つかるかどうかを確認します.
all-トラバース配列は、それぞれeqが存在するかどうかを確認します.
ex-着信値があると、サブ要素が存在する.
re-正規表現で文字列が合っているかどうかを判断します.
d-直接関数を呼び出して判断します.
書き終わりましたか?自分で書いたのが正しいかどうかはよく分かりません.これは次の文章で検討する内容です.まずデフォルトの演算子を追加します.
 
  
operators[""] = function(testValue, value) {
if (testValue instanceof Array) {
return operators["in"].apply(this, arguments);
} else if (testValue instanceof RegExp) {
return operators["re"].apply(this, arguments);
} else if (testValue instanceof Function) {
return operators["ld"].apply(this, arguments);
} else {
return operators["eq"].apply(this, arguments);
}
};
なぜデフォルトの演算子が必要ですか?これはただのショートカットです.ほとんどの場合、私たちが必要なのはeq演算です.一つ一つに演算子を記入すると、コードが複雑になり、見苦しいです.二つのJSONを比べてみて、どちらが自然だと思いますか?
 
  
Dispatcher.capture({
"status": 200,
"command": "message"
}, function(json) { /* display message */ });
Dispatcher.capture({
"status$eq": 200,
"command$eq": "message"
}, function(json) { /* display message */ });
明らかに、最初のほうが直感的です.したがって、デフォルトの演算子が必要です.演算子文字列が「」の場合は、デフォルトの演算子で演算子を選択します.
Pattern to Filter
最後に、私たちはoperatorsとcreateFilterをつなぐ必要があります.この部分の仕事は実は難しくないです.標準の演算子を呼べばいいです.
 
  
var createFilter = function(condition) {
return function(json) {
if (arguments.length > 0) {
return operators[""](condition, json);
} else {
return operators[""](condition);
}
};
};
なぜJsonパラメータが入っていないかを考慮する必要がありますか?今度の文章をまた教えます.そうしなくてもいいです.細かい問題があります.
演算子を書くには、最も必要なのは厳格さです.Displatchはパッケージの良い部品なので、演算子の少しの不厳格さは、いずれも欠陥を深く埋めて、見つけにくいです.したがって、次の文章では、ユニットテストについて議論します.ユニットテストによって、Displatchのたくましさを大幅に高めることができます.