JavaScript:对象重命名键

IT技术 javascript object key rename
2021-01-25 05:46:48

是否有一种聪明的(即优化的)方法来重命名 javascript 对象中的键?

一个非优化的方式是:

o[ new_key ] = o[ old_key ];
delete o[ old_key ];
6个回答

我相信,最完整(和正确)的方法是:

if (old_key !== new_key) {
    Object.defineProperty(o, new_key,
        Object.getOwnPropertyDescriptor(o, old_key));
    delete o[old_key];
}

此方法可确保重命名的属性原始属性的行为相同

此外,在我看来,将其包装成一个函数/方法并将其放入Object.prototype与您的问题无关。

如果重要,我相信 ES5 的这种特殊用法是 IE9 和更新的解决方案。
2021-03-25 05:46:48
我还建议添加一个o.new_key已经存在的验证,以避免覆盖。改变:if (old_key !== new_key && o[old_key])if (old_key !== new_key && o[old_key] && !o[new_key])
2021-03-25 05:46:48
我建议添加 o.old_key 存在的验证。更改: if (old_key !== new_key)到: if (old_key !== new_key && o[old_key])
2021-03-27 05:46:48
这是一个很好的 ES5-only 解决方案,具有保留所有属性的真正优势。所以这不是“优化”的,但在 ES5 上绝对更准确。
2021-04-01 05:46:48
对 write_things_with_underscores 持怀疑态度,但这当然是由于提出问题的人。在我看来,这是正确的回应。
2021-04-04 05:46:48

如果您正在修改源对象,ES6 可以在一行中完成。

delete Object.assign(o, {[newKey]: o[oldKey] })[oldKey];

如果你想创建一个新对象,或者两行。

const newObject = {};
delete Object.assign(newObject, o, {[newKey]: o[oldKey] })[oldKey];
如果您的变量名称更冗长,这个答案会更好。
2021-03-14 05:46:48
注意: Object.assign 的使用只做一个浅拷贝。
2021-03-14 05:46:48
好的 - 我得到了答案。这是 ES6 的特性。对于像我这样偶然发现的其他人,这是一个很好的答案
2021-03-21 05:46:48
尝试:删除 Object.assign(o, {newKey: o.oldKey }).oldKey; 对我来说效果很好
2021-03-25 05:46:48
为什么[]周围有方括号newKey该解决方案实际上没有那个。
2021-04-08 05:46:48

您可以将工作包装在一个函数中并将其分配给Object原型。也许使用流畅的界面风格来进行多次重命名。

Object.prototype.renameProperty = function (oldName, newName) {
     // Do nothing if the names are the same
     if (oldName === newName) {
         return this;
     }
    // Check for the old property name to avoid a ReferenceError in strict mode.
    if (this.hasOwnProperty(oldName)) {
        this[newName] = this[oldName];
        delete this[oldName];
    }
    return this;
};

ECMAScript 5 特定

我希望语法不是那么复杂,但拥有更多控制权绝对是件好事。

Object.defineProperty(
    Object.prototype, 
    'renameProperty',
    {
        writable : false, // Cannot alter this property
        enumerable : false, // Will not show up in a for-in loop.
        configurable : false, // Cannot be deleted via the delete operator
        value : function (oldName, newName) {
            // Do nothing if the names are the same
            if (oldName === newName) {
                return this;
            }
            // Check for the old property name to 
            // avoid a ReferenceError in strict mode.
            if (this.hasOwnProperty(oldName)) {
                this[newName] = this[oldName];
                delete this[oldName];
            }
            return this;
        }
    }
);
@ChaosPandion 对此表示抱歉,但我真的厌倦了漏洞百出的 JS 代码,我目前正在编写关于所有怪癖(包括您现在已修复的那个的指南 ( github.com/BonsaiDen/JavaScript-Garden ),这可能让我陷入某种咆哮模式;)(现在删除了 -1)
2021-03-22 05:46:48
@Ivo - 你能解释一下为什么你觉得扩展原型很糟糕吗?原型是为扩展婴儿而制作的!
2021-03-23 05:46:48
这段代码有效,但需要注意的是,如果新的键名已经存在,它的值将会被践踏:jsfiddle.net/ryurage/B7x8x
2021-03-30 05:46:48
@Ivo - 我同意这是有风险的,但如果我觉得它会导致更具表现力的代码,没有什么可以阻止我扩展原型。尽管我来自 ECMAScript 5 思维模式,您可以通过Object.defineProperty.
2021-04-05 05:46:48
@Ivo - 如果总是hasOwnProperty用来检查属性和for ... in循环是正确的做法,那么为什么我们扩展对象很重要?
2021-04-05 05:46:48

如果有人需要重命名属性列表:

function renameKeys(obj, newKeys) {
  const keyValues = Object.keys(obj).map(key => {
    const newKey = newKeys[key] || key;
    return { [newKey]: obj[key] };
  });
  return Object.assign({}, ...keyValues);
}

用法:

const obj = { a: "1", b: "2" };
const newKeys = { a: "A", c: "C" };
const renamedObj = renameKeys(obj, newKeys);
console.log(renamedObj);
// {A:"1", b:"2"}
这应该是可以接受的答案,对我的用例很有用。我必须转换一个 API 响应,该响应在国家/地区名称前加上不必要的字符串。将 Object 转换为键数组并使用 substring 方法映射到每个键,并返回一个具有新键和由原始键索引的值的新对象
2021-03-29 05:46:48
这很好,因为它不会删除旧密钥。如果键名未更改,删除旧键将从对象中完全删除键。在我的示例中,我正在转换my_object_propertymyObjectProperty,但是,如果我的属性是单字的,那么密钥将被删除。+1
2021-04-07 05:46:48

我只想用的ES6(ES2015)方式!

我们需要与时俱进!

const old_obj = {
    k1: `111`,
    k2: `222`,
    k3: `333`
};
console.log(`old_obj =\n`, old_obj);
// {k1: "111", k2: "222", k3: "333"}


/**
 * @author xgqfrms
 * @description ES6 ...spread & Destructuring Assignment
 */

const {
    k1: kA, 
    k2: kB, 
    k3: kC,
} = {...old_obj}

console.log(`kA = ${kA},`, `kB = ${kB},`, `kC = ${kC}\n`);
// kA = 111, kB = 222, kC = 333

const new_obj = Object.assign(
    {},
    {
        kA,
        kB,
        kC
    }
);

console.log(`new_obj =\n`, new_obj);
// {kA: "111", kB: "222", kC: "333"}

演示屏幕快捷方式

不错,但我认为 const {k1: kA, k2: kB, k3: kC,} = old_obj 就足够了吗?无需传播(除非您想要一份 old_obj 的副本)。
2021-03-13 05:46:48
@Hans,是的,你是对的。但是在这种情况下,我想重命名一些键,所以我应该传播它们。
2021-03-16 05:46:48
当您想将格式错误的对象转换为全新的重组对象时,发现这是一种更简洁的解决方案。
2021-03-20 05:46:48
这需要更多的代码,效率会更低,并且会创建一个新对象。重命名属性意味着改变对象。新的并不总是更好。
2021-04-02 05:46:48