Javascript 在迭代对象的键时重命名它们是否安全?
我在迭代对象的键时重命名它们:Javascript 在迭代对象的键时重命名它们是否安全?,javascript,json,node.js,Javascript,Json,Node.js,我在迭代对象的键时重命名它们: Object.keys(object).forEach(function(oldKey) { var newKey = someFunc(oldKey); if (newKey !== oldKey) { object[newKey] = object[oldKey]; delete object[oldKey]; } } 我想知道这种方法是否安全 换句话说,我可以确保我的代码永远不会迭代在上一次迭代中重命
Object.keys(object).forEach(function(oldKey) {
var newKey = someFunc(oldKey);
if (newKey !== oldKey) {
object[newKey] = object[oldKey];
delete object[oldKey];
}
}
我想知道这种方法是否安全
换句话说,我可以确保我的代码永远不会迭代在上一次迭代中重命名的键吗?对象。键与许多其他方法一样,返回可以迭代的数组。此数组不是“活动”数组,而是拍摄时的快照(例如,执行Object.keys
)。因此,是的,您可以按预期使用它
很少有方法返回“实时列表”而不是数组;我想您已经记住了,当您使用document.queryselectoral时会得到。然而,这不是一个数组,而是一个节点列表
然而,我可以看到一个陷阱:当一个生成的newKey已经存在于oldkey列表中时(不是当前的!)。因此,您可以或不可以(取决于数组中的位置)迭代已覆盖的新密钥。不,您不安全。您正在基于非活动数组对对象进行活动变异。如果你碰巧将一个新名字与一个旧名字交叉(将a重命名为b,但b已经存在,而且还没有到达),你会过得很糟糕
您不会遇到已经看到的键,但无法知道对象中是否尚未找到newKey
有一些变通方法,这种情况类似于迭代数组时对数组进行加密(删除元素),简单的变通方法是向后迭代,以便始终传递修改过的键。(或者在您的情况下,请与
操作员中的进行检查)
但是,创建并返回新对象会更好:
const newObj = Object.keys(object).reduce(function(result, oldKey) {
var newKey = someFunc(oldKey);
return { ...result, [newKey]: object[oldKey] };
}, {});
如果您将所有数据结构视为不可变的(更具体地说,当密钥从未更改时),您可以免费获得很多东西。下面是一个在不创建新对象的情况下更改密钥的解决方案
for(key in obj){
Object.defineProperty(obj, `myNewName`, Object.getOwnPropertyDescriptor(obj, key));
delete obj[key];
}
你自相矛盾。这最后一点正是为什么答案是,你不安全的变异对象作为OP提出。这个问题不必与DOM,但我想我会澄清一些东西,现在删除的答案说。它错误地指出querySelectorAll
返回一个实时列表。有动态和静态版本的NodeList
,querySelectorAll
实际上返回一个静态(非活动)节点列表。一些较旧的DOM接口,如Node.childNodes
返回一个活动的NodeList
,同样,一些较旧的接口,如getElementsByTagName
返回一个始终活动的HTMLCollection
。如果文档中说它返回了一个数组
(像'Object.keys那样),那么该数据是非活动的。非常感谢。如果我确信我永远不会生成一个已经存在的密钥呢?我发布的代码中并没有保证这一点,因为someFunc
似乎对object
一无所知,但让我们假设情况确实如此(因为在我的完整程序中是这样的)。那么我安全了吗?@Goodscibration根据我的经验,问题是这个假设在今天是正确的,但在将来不会是正确的,到那时,代码中假设的存在将被忘记,你很难找到/调试bug。没有理由不在这里创建一个新对象,性能增益可以忽略不计。我不认为我在创建一个新对象。你是对的@goodvibration。但带“.reduce”的答案是正确的。我并不是说我的答案更好,我只是想展示一种不同的方法:-)好的,但您可能应该在代码中将中的“myNewName”
更改为someFunc(key)
。