用JavaScript對JSON進行模式比對 (Part 2 – 實現)

來源:互聯網
上載者:User

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);
}
}
};

這段代碼的邏輯很清晰,關鍵就在於 createFilter 的部分。這個函數負責把一個描述模式的 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 的含義就是 == ;對於 Array , eq 的含義就是裡面的每一個元素都 eq ,而且順序一致;對於 Object , eq 的含義是每一個子條件都符合,因此我們需要將每一個子條件的運算子字串提取出來,然後調用對應的運算子。具體可以參考完整代碼。
其他運算子會簡單一些,在此我僅僅給出提示,大家可以根據自己的實際需求這些運算子的子集或超集:

in - 遍曆數組,看能否找到至少一個 eq 的。
all - 遍曆數組,看是否每一個都存在 eq 的。
ex - 如果有傳入值,則子項目存在。
re - 用Regex判斷字串是否匹配。
ld - 直接調用函數進行判斷。
寫好了嗎?不太確信自己寫得是否正確?這是我們下一篇文章要討論的內容,讓我們先加上一個預設運算子。 複製代碼 代碼如下: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 參數沒有傳入的情況?下次文章再告訴你。不這樣做也可以,只是有些很細小的問題而已。
寫運算子,最需要的是嚴謹性。因為 Dispatcher 是一個封裝好的組件,運算子一點點的不嚴謹,都會把缺陷埋藏得很深,很難找出來。因此,下一篇文章我們要討論的是單元測試,通過單元測試我們可以大大提高 Dispatcher 的健壯性。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.