在迭代对象时重命名对象的密钥是否安全?

时间:2018-10-07 10:02:52

标签: javascript json node.js

我在迭代对象时重命名它们:

Object.keys(object).forEach(function(oldKey) {
    var newKey = someFunc(oldKey);
    if (newKey !== oldKey) {
        object[newKey] = object[oldKey];
        delete object[oldKey];
    }
}

我想知道这种方法是否安全。

换句话说,我可以确定我的代码永远不会迭代在先前迭代中已重命名的键吗?

非常感谢!!

3 个答案:

答案 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];
}