Có cách nào thông minh (tức là tối ưu hóa) để đổi tên khóa trong đối tượng javascript không?
Một cách không được tối ưu hóa sẽ là:
o[ new_key ] = o[ old_key ];
delete o[ old_key ];
Có cách nào thông minh (tức là tối ưu hóa) để đổi tên khóa trong đối tượng javascript không?
Một cách không được tối ưu hóa sẽ là:
o[ new_key ] = o[ old_key ];
delete o[ old_key ];
Câu trả lời:
Cách tốt nhất (và chính xác) để làm điều này sẽ là, tôi tin:
if (old_key !== new_key) {
Object.defineProperty(o, new_key,
Object.getOwnPropertyDescriptor(o, old_key));
delete o[old_key];
}
Phương pháp này đảm bảo rằng thuộc tính được đổi tên hoạt động giống hệt với tài sản ban đầu.
Ngoài ra, đối với tôi, khả năng bao bọc nó thành một hàm / phương thức và đưa nó vào Object.prototype
là không liên quan đến câu hỏi của bạn.
if (old_key !== new_key)
đến: if (old_key !== new_key && o[old_key])
Bạn có thể gói công việc trong một hàm và gán nó cho Object
nguyên mẫu. Có thể sử dụng kiểu giao diện trôi chảy để thực hiện nhiều lần đổi tên.
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 Cụ thể
Tôi ước cú pháp không phức tạp nhưng chắc chắn sẽ có nhiều quyền kiểm soát hơn.
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
để kiểm tra các thuộc tính và trong for ... in
các vòng lặp, thì tại sao chúng ta lại mở rộng Object?
Nếu bạn đang thay đổi đối tượng nguồn của mình, ES6 có thể thực hiện điều đó trong một dòng.
delete Object.assign(o, {[newKey]: o[oldKey] })[oldKey];
Hoặc hai dòng nếu bạn muốn tạo một đối tượng mới.
const newObject = {};
delete Object.assign(newObject, o, {[newKey]: o[oldKey] })[oldKey];
[]
xung quanh newKey
? Các giải pháp hoạt động mà không thực sự đó.
Trong trường hợp ai đó cần đổi tên danh sách tài sản:
function renameKeys(obj, newKeys) {
const keyValues = Object.keys(obj).map(key => {
const newKey = newKeys[key] || key;
return { [newKey]: obj[key] };
});
return Object.assign({}, ...keyValues);
}
Sử dụng:
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
sang myObjectProperty
, tuy nhiên, nếu tài sản của tôi là một từ, thì khóa đã bị xóa. +1
ES6(ES2015)
cách!chúng ta cần theo kịp thời đại!
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"}
Nếu bạn không muốn thay đổi dữ liệu của mình, hãy xem xét chức năng này ...
renameProp = (oldProp, newProp, {[oldProp]:old, ...others}) => ({
[newProp]: old,
...others
})
Một lời giải thích kỹ lưỡng của Yazeed Bzadough https://medium.com/front-end-hacking/immutingly-rename-object-keys-in-javascript-5f6353c7b6dd
Hầu hết các câu trả lời ở đây không duy trì thứ tự cặp giá trị khóa-đối tượng JS. Ví dụ, nếu bạn có một dạng cặp khóa-giá trị đối tượng trên màn hình mà bạn muốn sửa đổi, điều quan trọng là phải giữ nguyên thứ tự của các mục nhập đối tượng.
Cách ES6 lặp qua đối tượng JS và thay thế cặp khóa-giá trị bằng cặp mới bằng tên khóa đã sửa đổi sẽ giống như:
let newWordsObject = {};
Object.keys(oldObject).forEach(key => {
if (key === oldKey) {
let newPair = { [newKey]: oldObject[oldKey] };
newWordsObject = { ...newWordsObject, ...newPair }
} else {
newWordsObject = { ...newWordsObject, [key]: oldObject[key] }
}
});
Giải pháp duy trì thứ tự của các mục bằng cách thêm mục mới vào vị trí của mục cũ.
Bạn có thể thử 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>
Một biến thể sử dụng toán tử phá hủy và truyền bá đối tượng:
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};
Cá nhân, cách hiệu quả nhất để đổi tên các khóa trong đối tượng mà không cần thực hiện thêm các plugin và bánh xe nặng:
var str = JSON.stringify(object);
str = str.replace(/oldKey/g, 'newKey');
str = str.replace(/oldKey2/g, 'newKey2');
object = JSON.parse(str);
Bạn cũng có thể bọc nó try-catch
nếu đối tượng của bạn có cấu trúc không hợp lệ. Hoạt động hoàn hảo :)
'a'
trong { a: 1, aa: 2, aaa: 3}
hoặc cố gắng đổi tên một đối tượng với các giá trị là bất kỳ thứ gì ngoài chuỗi hoặc số hoặc booleans hoặc thử với các tham chiếu tròn.
Tôi sẽ làm một cái gì đó như thế này:
function renameKeys(dict, keyMap) {
return _.reduce(dict, function(newDict, val, oldKey) {
var newKey = keyMap[oldKey] || oldKey
newDict[newKey] = val
return newDict
}, {})
}
Tôi sẽ nói rằng sẽ tốt hơn nếu theo quan điểm khái niệm là chỉ để lại đối tượng cũ (đối tượng từ dịch vụ web), và đặt các giá trị bạn cần vào một đối tượng mới. Tôi giả sử rằng bạn đang trích xuất các trường cụ thể tại điểm này hay điểm khác, nếu không phải trên máy khách, thì ít nhất là trên máy chủ. Thực tế là bạn đã chọn sử dụng tên trường giống như tên từ dịch vụ web, chỉ chữ thường, không thực sự thay đổi điều này. Vì vậy, tôi khuyên bạn nên làm một cái gì đó như thế này:
var myObj = {
field1: theirObj.FIELD1,
field2: theirObj.FIELD2,
(etc)
}
Tất nhiên, tôi đang đưa ra tất cả các giả định ở đây, điều này có thể không đúng. Nếu điều này không áp dụng cho bạn hoặc nếu nó quá chậm (phải không? Tôi đã thử nghiệm, nhưng tôi tưởng tượng sự khác biệt sẽ nhỏ hơn khi số lượng trường tăng lên), xin vui lòng bỏ qua tất cả điều này :)
Nếu bạn không muốn làm điều này và bạn chỉ phải hỗ trợ các trình duyệt cụ thể, bạn cũng có thể sử dụng các getters mới để trả về "chữ hoa (trường)": xem http://robertnyman.com/2009/05/28 / getters-and-setters-with-javascript-code-samples-and-demos / và các liên kết trên trang đó để biết thêm thông tin.
BIÊN TẬP:
Thật đáng kinh ngạc, điều này cũng nhanh gần gấp đôi, ít nhất là trên FF3.5 của tôi khi làm việc. Xem: http://jsperf.com/spiny001
Mặc dù điều này không chính xác đưa ra một giải pháp tốt hơn để đổi tên khóa, nhưng nó cung cấp cách ES6 nhanh chóng và dễ dàng để đổi tên tất cả các khóa trong một đối tượng trong khi không làm thay đổi dữ liệu mà chúng chứa.
let b = {a: ["1"], b:["2"]};
Object.keys(b).map(id => {
b[`root_${id}`] = [...b[id]];
delete b[id];
});
console.log(b);
Một số giải pháp được liệt kê trên trang này có một số tác dụng phụ:
Đây là một giải pháp giữ vị trí của khóa ở cùng một vị trí và tương thích trong IE9 +, nhưng phải tạo một đối tượng mới và có thể không phải là giải pháp nhanh nhất:
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;
}
Xin lưu ý: IE9 có thể không hỗ trợ forEach ở chế độ nghiêm ngặt
Một cách khác với phương pháp GIẢM GIÁ mạnh mẽ nhất .
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);
Đây là một sửa đổi nhỏ mà tôi đã thực hiện cho chức năng của pomber; Để có thể lấy Mảng đối tượng thay vì một đối tượng và bạn cũng có thể kích hoạt chỉ mục. cũng có thể gán "Khóa" bằng một mảng
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;
}
kiểm tra
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);
Cách của bạn được tối ưu hóa, theo ý kiến của tôi. Nhưng bạn sẽ kết thúc với các phím được sắp xếp lại. Khóa mới được tạo sẽ được thêm vào cuối. Tôi biết bạn không bao giờ nên dựa vào thứ tự khóa, nhưng nếu bạn cần giữ nó, bạn sẽ cần phải đi qua tất cả các khóa và xây dựng từng đối tượng mới, thay thế khóa trong câu hỏi trong quá trình đó.
Như thế này:
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' };