underscore property name change javascript object key rename

property - JavaScript: Object Rename Key



javascript change property name (12)

¡Me gustaría usar la forma ES6(ES2015) !

¡Necesitamos estar al día con los tiempos!

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"}

¿Existe una forma inteligente (es decir, optimizada) de cambiar el nombre de una clave en un objeto javascript?

Una forma no optimizada sería:

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


Algunas de las soluciones enumeradas en esta página tienen algunos efectos secundarios:

  1. afecta la posición de la clave en el objeto, agregándola a la parte inferior (si esto es importante para usted)
  2. no funcionaría en IE9 + (de nuevo, si esto te importa)

Aquí hay una solución que mantiene la posición de la clave en el mismo lugar y es compatible con IE9 +, pero tiene que crear un nuevo objeto y puede que no sea la solución más rápida:

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; }

Tenga en cuenta: IE9 puede no admitir forEach en modo estricto


En caso de que alguien necesite cambiar el nombre de una lista de propiedades:

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

Uso:

const obj = { a: "1", b: "2" }; const newKeys = { a: "A", c: "C" }; const renamedObj = renameKeys(obj, newKeys); console.log(renamedObj); // {A:"1", b:"2"}


Esta es una pequeña modificación que hice a la función de Pomber; Para poder tomar una matriz de objetos en lugar de un objeto solo y también puede activar el índice. también las "claves" pueden ser asignadas por una matriz

function renameKeys(arrayObject, newKeys, index = false) { let newArray = []; arrayObject.forEach((obj,item)=>{ const keyValues = Object.keys(obj).map((key,i) => { return {[newKeys[i] || key]:obj[key]} }); let id = (index) ? {''ID'':item} : {}; newArray.push(Object.assign(id, ...keyValues)); }); return newArray; }

prueba

const obj = [{ a: "1", b: "2" }, { a: "5", b: "4" } ,{ a: "3", b: "0" }]; const newKeys = ["A","C"]; const renamedObj = renameKeys(obj, newKeys); console.log(renamedObj);


Haría algo como esto:

function renameKeys(dict, keyMap) { return _.reduce(dict, function(newDict, val, oldKey) { var newKey = keyMap[oldKey] || oldKey newDict[newKey] = val return newDict }, {}) }


La forma más completa (y correcta) de hacer esto sería, creo:

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

Este método asegura que la propiedad renombrada se comporte de manera idéntica a la original.

Además, me parece que la posibilidad de incluir esto en una función / método y ponerlo en Object.prototype es irrelevante con respecto a su pregunta.


Personalmente, la forma más efectiva de cambiar el nombre de las llaves en un objeto sin implementar plugins y ruedas extra pesados:

var str = JSON.stringify(object); str = str.replace(/oldKey/g, ''newKey''); str = str.replace(/oldKey2/g, ''newKey2''); object = JSON.parse(str);

También puede envolverlo en try-catch si su objeto tiene una estructura no válida. Funciona perfectamente :)


Podría envolver el trabajo en una función y asignarlo al prototipo Object . Tal vez use el estilo de interfaz fluida para hacer que fluyan múltiples renombramientos.

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 Específico

Desearía que la sintaxis no fuera tan compleja, pero definitivamente es bueno tener más control.

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; } } );


Si bien esto no da exactamente una mejor solución para cambiar el nombre de una clave, proporciona una forma rápida y fácil de ES6 para cambiar el nombre de todas las claves en un objeto sin mutar los datos que contienen.

let b = {a: ["1"], b:["2"]}; Object.keys(b).map(id => { b[`root_${id}`] = [...b[id]]; delete b[id]; }); console.log(b);


Si está mutando su objeto fuente, ES6 puede hacerlo en una línea.

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

O dos líneas si quieres crear un nuevo objeto.

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



Yo diría que sería mejor, desde un punto de vista conceptual, simplemente dejar el objeto antiguo (el del servicio web) tal como está y colocar los valores que necesita en un nuevo objeto. Supongo que está extrayendo campos específicos en un punto u otro de todos modos, si no está en el cliente, al menos en el servidor. El hecho de que haya elegido utilizar nombres de campo que sean los mismos que los del servicio web, solo en minúsculas, realmente no cambia esto. Por lo tanto, te aconsejo hacer algo como esto:

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

Por supuesto, estoy haciendo todo tipo de suposiciones aquí, que pueden no ser ciertas. Si esto no se aplica a usted, o si es demasiado lento (¿verdad? No lo he probado, pero imagino que la diferencia se reduce a medida que aumenta el número de campos), ignore todo esto :)

Si no desea hacer esto y solo tiene que admitir navegadores específicos, también puede usar los nuevos captadores para devolver "mayúsculas (campo)": consulte http://robertnyman.com/2009/05/28/getters-and-setters-with-javascript-code-samples-and-demos/ y los enlaces en esa página para obtener más información.

EDITAR:

Increíblemente, esto también es casi el doble de rápido, al menos en mi FF3.5 en el trabajo. Ver: http://jsperf.com/spiny001