Apakah ada cara pintar (yaitu dioptimalkan) untuk mengubah nama kunci dalam objek javascript?
Cara yang tidak dioptimalkan adalah:
o[ new_key ] = o[ old_key ];
delete o[ old_key ];
Apakah ada cara pintar (yaitu dioptimalkan) untuk mengubah nama kunci dalam objek javascript?
Cara yang tidak dioptimalkan adalah:
o[ new_key ] = o[ old_key ];
delete o[ old_key ];
Jawaban:
Saya yakin cara paling lengkap untuk melakukan ini adalah:
if (old_key !== new_key) {
Object.defineProperty(o, new_key,
Object.getOwnPropertyDescriptor(o, old_key));
delete o[old_key];
}
Metode ini memastikan bahwa properti yang diubah namanya berperilaku identik dengan yang asli.
Juga, bagi saya tampaknya kemungkinan untuk membungkus ini menjadi fungsi / metode dan memasukkannya ke dalam Object.prototype
tidak relevan dengan pertanyaan Anda.
if (old_key !== new_key)
untuk: if (old_key !== new_key && o[old_key])
Anda bisa membungkus pekerjaan dalam suatu fungsi dan menugaskannya ke Object
prototipe. Mungkin menggunakan gaya antarmuka yang lancar untuk membuat banyak aliran nama.
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 Spesifik
Saya berharap sintaksnya tidak serumit ini, tetapi sudah pasti bagus memiliki lebih banyak kontrol.
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;
}
}
);
Object.defineProperty
.
hasOwnProperty
untuk memeriksa properti dan dalam for ... in
loop, lalu mengapa itu penting jika kita memperluas Object?
Jika Anda bermutasi objek sumber Anda, ES6 dapat melakukannya dalam satu baris.
delete Object.assign(o, {[newKey]: o[oldKey] })[oldKey];
Atau dua baris jika Anda ingin membuat objek baru.
const newObject = {};
delete Object.assign(newObject, o, {[newKey]: o[oldKey] })[oldKey];
[]
di sekitar newKey
? Solusinya bekerja tanpa itu sebenarnya.
Jika seseorang perlu mengganti nama daftar properti:
function renameKeys(obj, newKeys) {
const keyValues = Object.keys(obj).map(key => {
const newKey = newKeys[key] || key;
return { [newKey]: obj[key] };
});
return Object.assign({}, ...keyValues);
}
Pemakaian:
const obj = { a: "1", b: "2" };
const newKeys = { a: "A", c: "C" };
const renamedObj = renameKeys(obj, newKeys);
console.log(renamedObj);
// {A:"1", b:"2"}
my_object_property
ke myObjectProperty
, namun, jika properti saya adalah satu-worded, maka kuncinya telah dihapus. +1
ES6(ES2015)
caranya!kita perlu mengikuti perkembangan zaman!
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"}
Jika Anda tidak ingin mengubah data Anda, pertimbangkan fungsi ini ...
renameProp = (oldProp, newProp, {[oldProp]:old, ...others}) => ({
[newProp]: old,
...others
})
Penjelasan menyeluruh oleh Yazeed Bzadough https://medium.com/front-end-hacking/immutably-rename-object-keys-in-javascript-5f6353c7b6dd
Sebagian besar jawaban di sini gagal mempertahankan urutan pasangan kunci-nilai Objek JS. Jika Anda memiliki bentuk pasangan nilai kunci objek pada layar yang ingin Anda modifikasi, misalnya, penting untuk mempertahankan urutan entri objek.
Cara ES6 untuk mengulang melalui objek JS dan mengganti pasangan nilai kunci dengan pasangan baru dengan nama kunci yang dimodifikasi akan menjadi sesuatu seperti:
let newWordsObject = {};
Object.keys(oldObject).forEach(key => {
if (key === oldKey) {
let newPair = { [newKey]: oldObject[oldKey] };
newWordsObject = { ...newWordsObject, ...newPair }
} else {
newWordsObject = { ...newWordsObject, [key]: oldObject[key] }
}
});
Solusi mempertahankan urutan entri dengan menambahkan entri baru di tempat yang lama.
Anda dapat mencoba Lodash _.mapKeys
.
var user = {
name: "Andrew",
id: 25,
reported: false
};
var renamed = _.mapKeys(user, function(value, key) {
return key + "_" + user.id;
});
console.log(renamed);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
Variasi menggunakan operator perusakan dan penyebaran objek:
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 the renamed properties kA, kB, kC;
// spread the remaining original properties in the 'rest' variable
const newObj = {kA, kB, kC, ...rest};
Secara pribadi, cara paling efektif untuk mengubah nama kunci pada objek tanpa menerapkan plugins dan roda ekstra berat:
var str = JSON.stringify(object);
str = str.replace(/oldKey/g, 'newKey');
str = str.replace(/oldKey2/g, 'newKey2');
object = JSON.parse(str);
Anda juga dapat membungkusnya try-catch
jika objek Anda memiliki struktur yang tidak valid. Bekerja dengan sempurna :)
'a'
di { a: 1, aa: 2, aaa: 3}
atau mencoba untuk mengubah nama objek dengan nilai-nilai yang sesuatu yang lebih dari string atau angka atau boolean, atau mencoba dengan referensi melingkar.
Saya akan melakukan sesuatu seperti ini:
function renameKeys(dict, keyMap) {
return _.reduce(dict, function(newDict, val, oldKey) {
var newKey = keyMap[oldKey] || oldKey
newDict[newKey] = val
return newDict
}, {})
}
Saya akan mengatakan bahwa akan lebih baik dari sudut pandang konseptual untuk meninggalkan objek lama (yang dari layanan web) apa adanya, dan menempatkan nilai-nilai yang Anda butuhkan dalam objek baru. Saya berasumsi Anda mengekstraksi bidang tertentu pada satu titik atau yang lain, jika tidak pada klien, maka setidaknya di server. Fakta bahwa Anda memilih untuk menggunakan nama bidang yang sama dengan yang dari layanan web, hanya huruf kecil, tidak benar-benar mengubah ini. Jadi, saya menyarankan untuk melakukan sesuatu seperti ini:
var myObj = {
field1: theirObj.FIELD1,
field2: theirObj.FIELD2,
(etc)
}
Tentu saja, saya membuat segala macam asumsi di sini, yang mungkin tidak benar. Jika ini tidak berlaku untuk Anda, atau jika terlalu lambat (bukan? Saya belum menguji, tapi saya membayangkan perbedaannya semakin kecil dengan meningkatnya jumlah bidang), abaikan semua ini :)
Jika Anda tidak ingin melakukan ini, dan Anda hanya perlu mendukung browser tertentu, Anda juga dapat menggunakan getter baru untuk juga mengembalikan "huruf besar (bidang)": lihat http://robertnyman.com/2009/05/28 / getters-and-setters-with-javascript-code-samples-and-demo / dan tautan pada halaman itu untuk informasi lebih lanjut.
EDIT:
Luar biasa, ini juga hampir dua kali lebih cepat, setidaknya pada FF3.5 saya di tempat kerja. Lihat: http://jsperf.com/spiny001
Meskipun ini tidak memberikan solusi yang lebih baik untuk mengganti nama kunci, ini menyediakan cara ES6 yang cepat dan mudah untuk mengganti nama semua kunci dalam suatu objek tanpa mengubah data yang dikandungnya.
let b = {a: ["1"], b:["2"]};
Object.keys(b).map(id => {
b[`root_${id}`] = [...b[id]];
delete b[id];
});
console.log(b);
Beberapa solusi yang tercantum di halaman ini memiliki beberapa efek samping:
Berikut adalah solusi yang menjaga posisi kunci di tempat yang sama dan kompatibel di IE9 +, tetapi harus membuat objek baru dan mungkin bukan solusi tercepat:
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;
}
Harap dicatat: IE9 mungkin tidak mendukung untukEach dalam mode ketat
Namun cara lain dengan metode REDUCE paling kuat .
data = {key1: "value1", key2: "value2", key3: "value3"};
keyMap = {key1: "firstkey", key2: "secondkey", key3: "thirdkey"};
mappedData = Object.keys(keyMap).reduce((obj,k) => Object.assign(obj, { [keyMap[k]]: data[k] }),{});
console.log(mappedData);
Ini adalah modifikasi kecil yang saya buat untuk fungsi pomber; Untuk dapat mengambil Array Objek alih-alih objek saja dan Anda juga dapat mengaktifkan indeks. "Tombol" juga dapat ditetapkan oleh array
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;
}
uji
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);
Cara Anda dioptimalkan, menurut saya. Tetapi Anda akan berakhir dengan kunci yang dipesan ulang. Kunci yang baru dibuat akan ditambahkan di bagian akhir. Saya tahu Anda tidak boleh bergantung pada urutan kunci, tetapi jika Anda harus melestarikannya, Anda harus memeriksa semua kunci dan membuat objek baru satu per satu, mengganti kunci yang dimaksud selama proses itu.
Seperti ini:
var new_o={};
for (var i in o)
{
if (i==old_key) new_o[new_key]=o[old_key];
else new_o[i]=o[i];
}
o=new_o;
npm i paix
import { paix } from 'paix';
const source_object = { FirstName: "Jhon", LastName: "Doe", Ignored: true };
const replacement = { FirstName: 'first_name', LastName: 'last_name' };
const modified_object = paix(source_object, replacement);
console.log(modified_object);
// { Ignored: true, first_name: 'Jhon', last_name: 'Doe' };