在写一个物流模版编辑的时候,遇到这样一个需求:如果用户编辑一个已经存在的物流模版,如果数据没有发生变化,就阻止用户提交。这样后台就不用重新写入数据库。当时觉得这不是什么大问题,就放开了。
后面在写一个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了。