我在dataTree中有很多带子项的对象,我想用es6语法递归更新切换值为true并返回更新后的dataTree
对象看起来像这样
{
name: "Misc",
toggled: true,
children: [{
name: "Apple",
toggled:false
children: [{
name: "banana",
toggled:false
}]
}]
}
等...
任何想法,谢谢
答案 0 :(得分:1)
为您的{ name, toggled, children }
类型创建一个模块 - 我们称之为Node
const Node =
{ make : (name = "", toggled = false, children = []) =>
({ name, toggled, children })
, toggle : (node) =>
Node.make (node.name, !node.toggled, node.children)
, toggleAll : (node) =>
Node.make (node.name, !node.toggled, node.children.map (Node.toggleAll))
}
请注意,toggle
和toggleAll
不会改变原始输入 - 而是始终创建新节点
const n =
Node.make ("foo", true)
console.log (n, Node.toggle (n), n)
// { name: 'foo', toggled: true, children: [] }
// { name: 'foo', toggled: false, children: [] }
// { name: 'foo', toggled: true, children: [] }
我们可以直接在data
上使用此功能来切换所有toggled
字段
const data =
{ name : "Misc"
, toggled : true
, children :
[ { name : "Apple"
, toggled : false
, children :
[ { name : "banana"
, toggled : false
, children : []
}
]
}
]
}
console.log (Node.toggleAll (data))
// { name : "Misc"
// , toggled : false <--- toggled
// , children :
// [ { name : "Apple"
// , toggled : true <--- toggled
// , children :
// [ { name : "banana"
// , toggled : true <--- toggled
// , children : []
// }
// ]
// }
// ]
// }
但是,不应使用对象文字语法编写数据,而应使用模块
const data =
Node.make ( "Misc"
, true
, [ Node.make ( "Apple"
, false
, [ Node.make ("banana", false) ]
)
]
)
console.log (Node.toggleAll (data))
// same output
我想以递归方式将切换值更新为true ...
如果要将所有toggled
设置为特定值,可以为其编写特定函数
const Node =
{ ...
, toggleAllOn : (node) =>
Node.make (node.name, true, node.children.map (Node.toggleAllOn))
}
或者,我们可以使用参数
使原始Node.toggle
和Node.toggleAll
更灵活,而不是制作大量特定功能
const TOGGLE =
Symbol ()
const Node =
{ make : (name = "", toggled = false, children = []) =>
({ name, toggled, children })
, toggle : (node, value = TOGGLE) =>
Node.make ( node.name
, value === TOGGLE ? !node.toggled : Boolean (value)
, node.children
)
, toggleAll : (node, value = TOGGLE) =>
Node.make ( node.name
, value === TOGGLE ? !node.toggled : Boolean (value)
, node.children.map (n => Node.toggleAll (n, value))
)
}
现在我们可以使用n
切换节点Node.toggle (n)
或使用Node.toggle (n, true)
或Node.toggle (n, false)
const n =
Node.make ("foo", true)
console.log (n, Node.toggle (n, true), Node.toggle (n), n)
// { name: 'foo', toggled: true, children: [] } <--- original
// { name: 'foo', toggled: true, children: [] } <--- already true; no change
// { name: 'foo', toggled: false, children: [] } <--- toggled
// { name: 'foo', toggled: true, children: [] } <--- immutable
当然它也适用于Node.toggleAll (n, true)
const allTrue =
Node.toggleAll (data, true)
console.log (allTrue)
// { name : "Misc"
// , toggled : true <--- same value
// , children :
// [ { name : "Apple"
// , toggled : true <--- set to true
// , children :
// [ { name : "banana"
// , toggled : true <--- set to true
// , children : []
// }
// ]
// }
// ]
// }
程序演示
const TOGGLE =
Symbol ()
const Node =
{ make : (name = "", toggled = false, children = []) =>
({ name, toggled, children })
, toggle : (node, value = TOGGLE) =>
Node.make ( node.name
, value === TOGGLE ? !node.toggled : value
, node.children
)
, toggleAll : (node, value = TOGGLE) =>
Node.make ( node.name
, value === TOGGLE ? !node.toggled : value
, node.children.map (n => Node.toggleAll (n, value))
)
}
const data =
Node.make ( "Misc"
, true
, [ Node.make ( "Apple"
, false
, [ Node.make ("banana", false) ]
)
]
)
// display original
console.log ('original', data)
// only toggle this node
console.log ('toggle', Node.toggle (data))
// toggle this node and all children
console.log ('toggleAll', Node.toggleAll (data))
// set this node and all children to true
console.log ('toggleAll true', Node.toggleAll (data, true))
// check original data is not mutated (OK!)
console.log ('original', data)
&#13;
答案 1 :(得分:0)
我不确定这是不是你想要的,但我试过了。
var obj = {
name: "Misc",
toggled: true,
children: [{
name: "Apple",
toggled:false,
children: [{
name: "banana",
toggled:false
}]
}]
};
var toggleToTrue = function(obj){
if (!obj) { return false; }
obj.toggled = true;
if (!obj.children) { return false; }
var childs = obj.children;
for (var i in childs){
toggleToTrue(childs[i]);
}
};
toggleToTrue(obj);
console.log(obj);
答案 2 :(得分:0)
您可以将以下内容用于不会改变原始对象的递归解决方案,不会为没有这些属性的对象添加属性(如果对象添加toggled
它没有它,并且可以由调用者配置来改变某些行为:
var obj = {
name: "Misc",
toggled: true,
children: [{
name: "Apple",
toggled:false,
children: [{
name: "banana",
toggled:false
}]
}]
};
const changeProp = (shouldSet,set,doRecursive,rec) => calcValue => (obj) => {
const toggle = o => {
if (shouldSet(o)) {
return set({ ...o },calcValue(o));
}
return o;
};
return (!doRecursive(obj))
? toggle(obj)
: rec(toggle(obj),changeProp(shouldSet,set,doRecursive,rec)(calcValue))
};
const hasChild = o=>(o.hasOwnProperty("children") && Array.isArray(o.children));
const setRecursive = (o,rec)=>({
...o,
children:o.children.map(rec)
});
//set toggled to true
console.log(
changeProp(
o=>(typeof o.toggled === "boolean"),//should set function
(o,value)=>{o.toggled=value;return o; },//set function
hasChild,//do recursive?
setRecursive//recursively set
)(()=>true)//calculate value based on object (value is always true)
(obj)
);
//upper case name
console.log(
changeProp(
o=>(typeof o.name === "string"),//should set function
(o,value)=>{o.name=value;return o; },//set function
hasChild,//do recursive?
setRecursive//recursively set
)((o)=>o.name.toUpperCase())//calculate value based on object (name to uppercase)
(obj)
);
&#13;