JavaScript中删除对象时的异常行为及原因咨询
递归删除节点:为什么两个函数行为不同?
这事儿核心在于JavaScript里对象引用的工作机制,以及delete操作符到底能删什么——咱们一步步拆解:
1. 先看deleteNode为啥失效
当你在deleteNode里写delete bigObjectToSearch时,你删的只是函数内部的一个「局部引用」,根本碰不到原数组里的对象:
- 函数参数
bigObjectToSearch是原数组中目标对象的引用副本——它和原数组里的元素指向内存中同一个对象,但这个变量本身只存在于当前函数的作用域里。 delete在这里只是把这个局部变量的引用销毁了,原数组(也就是obj.children)依然握着对目标对象的引用,所以你console.log(obj)的时候,那个节点还在。
举个极简版的例子帮你理解:
let team = [{id: '236448654', name: 'Chun Miao'}]; let tempRef = team[0]; // 复制一个引用 delete tempRef; // 删的只是tempRef这个局部变量 console.log(team); // 输出还是 [{id: '236448654', name: 'Chun Miao'}]
2. 再看deleteNodeFromArray为啥生效
这个函数里,你是直接操作原数据结构的数组元素:
- 当递归找到目标节点后,函数返回
true,回到父节点的循环里。这时候你用bigObjectToSearch.children[i],直接指向了原数组中那个元素的位置。 delete在这里移除的是数组对该对象的引用,原数据结构被直接修改,所以目标节点从obj里消失了。
小补充:其实用splice比delete更靠谱,因为delete只会把数组对应位置变成undefined,不会缩短数组长度。改成这样效果更好:
// 替换delete bigObjectToSearch.children[i]; bigObjectToSearch.children.splice(i, 1);
总结一下两个函数的差异
deleteNode:找到节点后,试图删除的是函数内部的局部引用,和原数据结构完全无关,相当于白忙活。deleteNodeFromArray:找到节点后,回到父节点的上下文,直接修改父节点的children数组,把对应位置的元素删掉,这才真正修改了原对象。
内容的提问来源于stack exchange,提问作者jasmin_makasana
相关产品推荐
相关产品推荐

