JavaScript: объект переименовать ключ - PullRequest
223 голосов
/ 10 января 2011

Есть ли умный (т.е. оптимизированный) способ переименования ключа в объекте javascript?

Неоптимизированный способ будет:

o[ new_key ] = o[ old_key ];
delete o[ old_key ];

Ответы [ 17 ]

160 голосов
/ 30 января 2013

Самый полный (и правильный) способ сделать это, я полагаю:

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

Этот метод гарантирует, что переименованное свойство ведет себя идентично с исходным.

Кроме того, мне кажется, что возможность заключить это в функцию / метод и поместить в Object.prototype не имеет отношения к вашему вопросу.

89 голосов
/ 10 января 2011

Вы можете заключить работу в функцию и назначить ее прототипу 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;
        }
    }
);
44 голосов
/ 30 апреля 2018

Если вы изменяете исходный объект, ES6 может сделать это в одну строку.

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

Или две строки, если вы хотите создать новый объект.

const newObject = {};
delete Object.assign(newObject, o, {[newKey]: o[oldKey] })[oldKey];
30 голосов
/ 24 июля 2017

На случай, если кому-то нужно переименовать список свойств:

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"}
17 голосов
/ 10 ноября 2017

Я бы хотел использовать способ 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"}

demo screen shortcut

6 голосов
/ 24 апреля 2018

Если вы не хотите изменять данные, рассмотрите эту функцию ...

renameProp = (oldProp, newProp, {[oldProp]:old, ...others}) => ({
    [newProp]: old,
    ...others
})

Полное объяснение Язида Бзадоу https://medium.com/front-end-hacking/immutably-rename-object-keys-in-javascript-5f6353c7b6dd


5 голосов
/ 13 декабря 2018

Вариант с использованием оператора деструктурирования и распространения объекта:

    const old_obj = {
        k1: `111`,
        k2: `222`,
        k3: `333`
    };


// destructuring, with renaming. The variable rest will hold those values not assigned to kA, kB, or kC.
    const {
        k1: kA, 
        k2: kB, 
        k3: kC,
        ...rest
    } = old_obj;


// now create a new object, with shorthand properties **kA, kB, kC**; 
// spread the remaining properties in the **rest** variable
const newObj = {kA, kB, kC, ...rest};
4 голосов
/ 28 июля 2015

Я бы сделал что-то вроде этого:

function renameKeys(dict, keyMap) {
  return _.reduce(dict, function(newDict, val, oldKey) {
    var newKey = keyMap[oldKey] || oldKey
    newDict[newKey] = val 
    return newDict
  }, {})
}
3 голосов
/ 11 января 2011

Я бы сказал, что было бы лучше с концептуальной точки зрения просто оставить старый объект (объект из веб-службы) как есть и поместить нужные значения в новый объект. Я предполагаю, что вы в любом случае извлекаете определенные поля в тот или иной момент, если не на клиенте, то, по крайней мере, на сервере. Тот факт, что вы решили использовать имена полей, которые совпадают с именами из веб-службы, только в нижнем регистре, на самом деле не меняет этого. Итак, я бы посоветовал сделать что-то вроде этого:

var myObj = {
    field1: theirObj.FIELD1, 
    field2: theirObj.FIELD2,
    (etc)
}

Конечно, я делаю здесь всевозможные предположения, которые могут быть неверными. Если это не относится к вам, или если это слишком медленно (не так ли? Я не проверял, но я думаю, что разница уменьшается с увеличением количества полей), пожалуйста, игнорируйте все это:)

Если вы не хотите этого делать, и вам нужно только поддерживать определенные браузеры, вы также можете использовать новые методы получения, чтобы также возвращать "uppercase (field)": см. http://robertnyman.com/2009/05/28/getters-and-setters-with-javascript-code-samples-and-demos/ и ссылки эту страницу для получения дополнительной информации.

EDIT:

Невероятно, но это также почти вдвое быстрее, по крайней мере, на моем FF3.5 на работе. Смотри: http://jsperf.com/spiny001

2 голосов
/ 19 марта 2018

Некоторые из решений, перечисленных на этой странице, имеют некоторые побочные эффекты:

  1. влияют на положение ключа в объекте, добавляя его вниз (если это важно для вас)
  2. не будет работать в IE9 + (опять же, если это важно для вас)

Вот решение, которое сохраняет положение ключа в том же месте и совместимо с IE9 +, но имеетсоздать новый объект и может оказаться не самым быстрым решением:

function renameObjectKey(oldObj, oldName, newName) {
    const newObj = {};

    Object.keys(oldObj).forEach(key => {
        const value = oldObj[key];

        if (key === oldName) {
            newObj[newName] = value;
        } else {
            newObj[key] = value;
        }
    });

    return newObj;
}

Обратите внимание: IE9 может не поддерживать forEach в строгом режиме

...