我在迭代对象时重命名它们:
Object.keys(object).forEach(function(oldKey) {
var newKey = someFunc(oldKey);
if (newKey !== oldKey) {
object[newKey] = object[oldKey];
delete object[oldKey];
}
}
我想知道这种方法是否安全。
换句话说,我可以确定我的代码永远不会迭代在先前迭代中已重命名的键吗?
非常感谢!!
答案 0 :(得分:3)
不,您不安全。您正在基于非实时数组对实时对象进行突变。如果您碰巧将新名称与旧名称交叉使用(将a重命名为b,但是b已经存在并且尚未使用),您将会遇到麻烦。
您不会碰到已经看到的键,但是您无法知道对象中是否尚未找到newKey
。
有一些变通办法,这种情况类似于在迭代时.splice()
对数组(删除元素)进行迭代,而简单的变通办法是向后迭代,以便您始终已经传递了更改过的键。 (或者在您的情况下,请与in
运算符一起检查)
但是,创建并返回一个新对象要好得多
const newObj = Object.keys(object).reduce(function(result, oldKey) {
var newKey = someFunc(oldKey);
return { ...result, [newKey]: object[oldKey] };
}, {});
当您将所有数据结构都视为不可变时(更具体地说,当键永远不变时),您将免费获得许多东西
答案 1 :(得分:1)
Object.keys
返回一个可以迭代的 Array 。这个 Array 不是“活动的”,而是从获取时起的快照(例如,执行Object.keys
)。是的,您可以按预期使用它。
很少有返回“活动列表”而不是 Array 的方法的示例;我想您会想到NodeList,使用 document.querySelectorAll 时会得到。但是,这不是 Array ,而是 NodeList 。
但是,我可以看到一个陷阱:当 oldKey 列表中已经存在生成的 newKey 时(不是当前的!)。因此,您可能会或可能不会(取决于数组中的位置)遍历已经被覆盖的新键。
答案 2 :(得分:0)
这是一种无需创建新对象即可更改密钥的解决方案。
for(key in obj){
Object.defineProperty(obj, `myNewName`, Object.getOwnPropertyDescriptor(obj, key));
delete obj[key];
}