当我尝试从数组中删除对象时,我遇到了一些奇怪的行为。
请查看代码。我正在使用递归函数。
var obj = {
'id': '234567869',
'name': 'Lao Lao',
'title': 'general manager',
'children': [{
'id': '467876756634',
'name': 'Bo Miao',
'title': 'department manager'
}, {
'id': '2345666078',
'name': 'Su Miao',
'title': 'department manager',
'children': [{
'id': '898735342',
'name': 'Tie Hua',
'title': 'senior engineer'
}, {
'id': '7697347548',
'name': 'Hei Hei',
'title': 'senior engineer',
'children': [{
'id': '123415640',
'name': 'Pang Pang',
'title': 'engineer'
}, {
'id': '1237450976',
'name': 'Xiang Xiang',
'title': 'UE engineer'
}]
}]
}, {
'id': '6968756535',
'name': 'Yu Jie',
'title': 'department manager'
}, {
'id': '236448654',
'name': 'Chun Miao',
'title': 'department manager'
}, {
'id': '356898765',
'name': 'Yu Tie',
'title': 'department manager'
}]
};
function deleteNode(idToFind, bigObjectToSearch) {
var i, currentChild, result;
if (idToFind == bigObjectToSearch.id) {
//I try to delete the object here but can't :(
delete bigObjectToSearch;
return true;
} else if (bigObjectToSearch.children) {
for (i = 0; i < bigObjectToSearch.children.length; i += 1) {
currentChild = bigObjectToSearch.children[i];
// Search in the current child
if(deleteNode(idToFind, currentChild)){
break;
};
}
return false;
}
return false;
}
deleteNode('236448654', obj);
console.log(obj);
function deleteNodeFromArray(idToFind, bigObjectToSearch) {
var i, currentChild, result;
if (idToFind == bigObjectToSearch.id) {
//I try to delete the object here but can't :(
//delete bigObjectToSearch;
return true;
} else if (bigObjectToSearch.children) {
for (i = 0; i < bigObjectToSearch.children.length; i += 1) {
currentChild = bigObjectToSearch.children[i];
// Search in the current child
if(deleteNodeFromArray(idToFind, currentChild)){
//If I delete from here, it works.
delete bigObjectToSearch.children[i];
break;
};
}
return false;
}
return false;
}
deleteNodeFromArray('236448654', obj);
console.log(obj)
在第一个函数中,它不会删除id =“236448654”的对象。
在第二个函数中,它删除对象。两个功能代码都相同但是 只是删除语句有不同的位置。
任何人都可以解释一下这种行为吗?
谢谢。
答案 0 :(得分:1)
在谈论代码中的问题时,首先我要说使用delete并不是很好,因为它对V8类有负面影响
以下是删除工作原理的示例:
//
var keyToDelete = "key1";
var myObj = {
"test": {
"key1": "value",
"key2": "value"
}
}
delete myObj.test[keyToDelete];
console.log(myObj)
正如您所看到的那样,由于您的对象没有键,因此您需要删除的对象的键不是您的情况
为此,我不得不将对象数组中的对象编辑为对象对象,因为我无法在数组中设置键以便我们可以使用delete运算符,因此我还要删除deleteNodeFromArray
函数没有阵列就没有用了。
这是您的解决方案,需要进行必要的更正和优化:
//
var obj = {
"234567869": {
'id': '234567869',
'name': 'Lao Lao',
'title': 'general manager',
'children': {
"467876756634": {
'id': '467876756634',
'name': 'Bo Miao',
'title': 'department manager'
},
"2345666078": {
'id': '2345666078',
'name': 'Su Miao',
'title': 'department manager',
'children': {
"898735342": {
'id': '898735342',
'name': 'Tie Hua',
'title': 'senior engineer'
},
"7697347548": {
'id': '7697347548',
'name': 'Hei Hei',
'title': 'senior engineer',
'children': {
"123415640": {
'id': '123415640',
'name': 'Pang Pang',
'title': 'engineer'
},
"1237450976": {
'id': '1237450976',
'name': 'Xiang Xiang',
'title': 'UE engineer'
}
}
}
}
},
"6968756535": {
'id': '6968756535',
'name': 'Yu Jie',
'title': 'department manager'
},
"236448654": {
'id': '236448654',
'name': 'Chun Miao',
'title': 'department manager'
},
"356898765": {
'id': '356898765',
'name': 'Yu Tie',
'title': 'department manager'
}
}
}
};
function deleteNode(idToFind, bigObjectToSearch) {
var i, currentChild, result;
for (var key in bigObjectToSearch) {
if (idToFind == bigObjectToSearch[key].id) {
delete bigObjectToSearch[key];
} else if (bigObjectToSearch[key].children) {
deleteNode(idToFind, bigObjectToSearch[key].children)
}
}
}
deleteNode('7697347548', obj);
console.log(obj)
这是我从第一次编辑的旧(工作)解决方案,我使用了过滤器功能,因此我可以生成满足我需求的新对象:
//i changed the type of obj to array to it will be more easier to run the recursion
var obj = [{
'id': '234567869',
'name': 'Lao Lao',
'title': 'general manager',
'children': [{
'id': '467876756634',
'name': 'Bo Miao',
'title': 'department manager'
}, {
'id': '2345666078',
'name': 'Su Miao',
'title': 'department manager',
'children': [{
'id': '898735342',
'name': 'Tie Hua',
'title': 'senior engineer'
}, {
'id': '7697347548',
'name': 'Hei Hei',
'title': 'senior engineer',
'children': [{
'id': '123415640',
'name': 'Pang Pang',
'title': 'engineer'
}, {
'id': '1237450976',
'name': 'Xiang Xiang',
'title': 'UE engineer'
}]
}]
}, {
'id': '6968756535',
'name': 'Yu Jie',
'title': 'department manager'
}, {
'id': '236448654',
'name': 'Chun Miao',
'title': 'department manager'
}, {
'id': '356898765',
'name': 'Yu Tie',
'title': 'department manager'
}]
}];
// the recursive funtion that will call itself
function looperRec(obj, id) {
//delete the object that has the passed id from the array
var obj = obj.filter(function(item) {
return item.id !== id;
});
//loop the array in order to find the children
for (i in obj) {
// if children exist call the function again
if (obj[i].hasOwnProperty('children')) {
//replace the old data with the new one only when the attribute children exist
obj[i].children = looperRec(obj[i].children, id)
}
}
//return the result of each step in the recursion
return obj;
}
//display the result
console.log(looperRec(obj, "898735342"));
答案 1 :(得分:1)
纯递归
delete
被误解,但因为它会产生副作用(命令式),使用递归(函数样式)会导致一些冲突。
如果您编写纯函数,原始数据不会发生变异,而是#34; next&#34;返回数据的状态。这里的主要优点是你不必担心副作用。这自然会鼓励一种递归模式,其中节点的子节点是每个孩子调用removeNode
的结果。
const identity = x =>
x
const removeNode = (match, { id, name, title, children = [] }) =>
match === id
? null
: { id : id
, name : name
, title : title
, children : children.map (n => removeNode (match, n)) .filter (identity)
}
这是一个完整的演示
const identity = x =>
x
const removeNode = (match, { id, name, title, children = [] }) =>
match === id
? null
: { id : id
, name : name
, title : title
, children : children.map (n => removeNode (match, n)) .filter (identity)
}
const node =
{ id : "234567869"
, name : "Lao Lao"
, title : "general manager"
, children :
[ { id : "467876756634"
, name : "Bo Miao"
, title : "department manager"
}
, { id : "2345666078"
, name : "Su Miao"
, title : "department manager"
, children :
[ { id : "898735342"
, name : "Tie Hua"
, title : "senior engineer"
}
, { id : "7697347548"
, name : "Hei Hei"
, title : "senior engineer"
, children :
[ { id : "123415640"
, name : "Pang Pang"
, title : "engineer"
}
, { id : "1237450976"
, name : "Xiang Xiang"
, title : "UE engineer"
}
]
}
]
}
, { id : "6968756535"
, name : "Yu Jie"
, title : "department manager"
}
, { id : "236448654"
, name : "Chun Miao"
, title : "department manager"
}
, { id : "356898765"
, name : "Yu Tie"
, title : "department manager"
}
]
}
console.log (removeNode ("236448654", node))
&#13;
答案 2 :(得分:0)
关于垃圾收集器。您不能删除JS中的任何对象,所有这些都可以 - 它是在某个地方删除对象的引用。当您调用delete bigObjectToSearch;
或delete bigObjectToSearch.children[i];
时,它不会删除对象,它会尝试删除对该对象的引用 - 并且不要触摸对象本身。
此外,在第一个函数(此处为delete bigObjectToSearch;
)中,您尝试删除整个对象,而“删除”仅使用对象属性,因此您无法
在第二个函数中,您成功删除了对象属性,实际上它不是对象本身,只是链接到它们。所以,实际上“删除”对象仍然存在。它会存在,直到它们存在一些链接,如果没有 - 它会在某个时刻被垃圾收集。
在JS中你不能强制删除任何对象,你必须控制所有引用的不要创建内存泄漏。