在寫一個物流模版編輯的時候,遇到這樣一個需求:如果用戶編輯一個已經存在的物流模版,如果數據沒有發生變化,就阻止用戶提交。這樣后台就不用重新寫入數據庫。當時覺得這不是什么大問題,就放開了。
后面在寫一個Dialog組件時,遇到一個配置參數設置:將傳入的參數和默認參數相比較,如果傳入的參數設置了對應值,就跳過。如果沒有設置,就取默認參數的值。這里也就要比較兩個對象的key和value。
兩個條件:
- 初始數據克隆緩存下來。
- 新獲取的數據格式與初始數據一致。只是key或value值變化。
思路如下:
由於不能同時遍歷兩個對象,所以就需要以一個對象為基准對象,再去獲取對應的key的路徑。取出所有key的路徑和value一一比較。
需要兩個函數:
- 遞歸取得基准對象的key的子父級關系。
- 操作結果函數(比如比較是否相等或者將沒有key補上)
獲取基准對象的子父級路徑函數如下:
obj
為基准對象,是一個對象字面量fn
為回調函數recor
為一個數組,用於記錄key的層級路徑baseObj
基准對象compObj
對比對象
function recursion(obj, fn, recor, baseObj, compObj){
var key, cur;
if(obj && typeof obj === "object"){
for(key in obj){
if(!obj.hasOwnProperty(key)) continue;
recor.push(key);
cur = obj[key];
if(cur && typeof obj === "object"){
recursion(cur, fn, recor);
}
// 將記錄的層級關系數組傳入回調
fn(baseObj, compObj, recor);
recor.pop();
}
}
}
操作結果函數:通過路徑數組,依次檢查對象是否存在
baseObj
基准對象compObj
需要對比的對象keyArr
保存key值的數組
function compare(baseObj, compObj, keyArr){
var base = baseObj, comp = compObj, i, len, key;
for( i = 0, len = keyArr.length; i < len; i++){
key = keyArr[i];
// 如果比較對象沒有基准對象對應的key,將基准對象的值賦值給比較對象
// 並跳出循環
if(!comp.hasOwnProperty(key)){
comp[key] = base[key];
break;
}
// 比較下一個
comp = comp[key];
base = base[key];
}
}
調用
// 定義兩個對象
// 基准對象
var base_obj = {
"str" : "simple text",
"obj" : {
"o_str" : "simple obj text",
"arr" : [1, 2, 3],
"o_obj" : {
"boll" : true,
"tt" : "test"
}
}
}
// 對比對象
var comp_obj = {
"str" : "simple text",
"obj" : {
"o_str" : "simple obj text",
"arr" : [1, 2, 3]
}
}
// 調用
recursion(base_obj, compare, [], base_obj, comp_obj);
// 運行結果
comp_obj => {
"str" : "simple text",
"obj" : {
"o_str" : "simple obj text",
"arr" : [1, 2, 3],
"o_obj" : {
"boll" : true,
"tt" : "test"
}
}
}
如果要判斷相等,在compare中,如果comp.hasOwnPropery(key)為假,直接return false就是了。循環完了還沒有return,就可以return true了。