Який найкращий / стандартний спосіб об’єднання двох асоціативних масивів у JavaScript? Чи всі це роблять, прокручуючи власну for
петлю?
Який найкращий / стандартний спосіб об’єднання двох асоціативних масивів у JavaScript? Чи всі це роблять, прокручуючи власну for
петлю?
Відповіді:
за допомогою jquery ви можете зателефонувати $.extend
var obj1 = {a: 1, b: 2};
var obj2 = {a: 4, c: 110};
var obj3 = $.extend(obj1, obj2);
obj1 == obj3 == {a: 4, b: 2, c: 110} // Pseudo JS
(допоміжні масиви - це об'єкти в js)
дивіться тут: http://api.jquery.com/jQuery.extend/
редагувати: Як запропонував rymo, краще зробити це так:
obj3 = $.extend({}, obj1, obj2);
obj3 == {a: 4, b: 2, c: 110}
Оскільки тут obj1 (і obj2) залишаються незмінними.
edit2: У 2018 році спосіб зробити це через Object.assign
:
var obj3 = Object.assign({}, obj1, obj2);
obj3 === {a: 4, b: 2, c: 110} // Pseudo JS
Якщо працювати з ES6, цього можна досягти за допомогою оператора Spread :
const obj3 = { ...obj1, ...obj2 };
obj1
, використовуйте порожній об’єкт як ціль:$.extend({}, obj1, obj2)
Object.assign()
, яке не покладається на JQuery, якщо ви вже не використовуєте бібліотеку.
Зараз у 2016 році я б сказав, що найкращий / стандартний спосіб - Object.assign ()
Чистий Javascript. Не потрібен jQuery.
obj1 = {a: 1, b: 2};
obj2 = {a: 4, c: 110};
obj3 = Object.assign({},obj1, obj2); // Object {a: 4, b: 2, c: 110}
Більше інформації, приклади та полізаповнення тут:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
Ось як це робить прототип:
Object.extend = function(destination, source) {
for (var property in source) {
if (source.hasOwnProperty(property)) {
destination[property] = source[property];
}
}
return destination;
};
називається як, наприклад:
var arr1 = { robert: "bobby", john: "jack" };
var arr2 = { elizabeth: "liz", jennifer: "jen" };
var shortnames = Object.extend(arr1,arr2);
EDIT : додано перевірку hasOwnProperty (), як правильно вказав bucabay в коментарях
Не ускладнювати...
function mergeArray(array1,array2) {
for(item in array1) {
array2[item] = array1[item];
}
return array2;
}
arrau1.prototype
hasOwnProperty
перевірка. Посилання на об'єкти як масиви також вводить в оману (вони є об'єктами), назви аргументів повинні свідчити про те, що array2 мутується або новий об’єкт повинен бути повернутий. Я би відредагував відповідь, але фактично це стане майже точно відредагованою відповіддю Джонатана Фінгленда, яка вже виправлена.
Підкреслення також має метод розширення:
Скопіюйте всі властивості вихідних об'єктів на об'єкт призначення. Це в порядку, тож останнє джерело буде заміняти однойменні властивості в попередніх аргументах.
_.extend(destination, *sources)
_.extend({name : 'moe'}, {age : 50});
=> {name : 'moe', age : 50}
У доджо "2" об'єкти / масиви "злиття" було б lang.mixin(destination, source)
- ви також можете змішати кілька джерел в одне місце призначення тощо - для детальної інформації див. Посилання на функцію mixin .
чи хочете ви перезаписати властивість, якщо імена однакові, але значення немає?
І чи хочете ви назавжди змінити один з оригінальних об'єктів,
чи ви хочете повернути новий об'єднаний об’єкт?
function mergedObject(obj1, obj2, force){
for(var p in obj1) this[p]= obj1[p];
for(var p in obj2){
if(obj2.hasOwnProperty(p)){
if(force || this[p]=== undefined) this[p]= obj2[p];
else{
n= 2;
while(this[p+n]!== undefined)++n;
this[p+n]= obj2[p];
}
}
}
}
function extend(objects) {
var args
, first = Array.prototype.slice.call(arguments, 0, 1)[0]
, second;
if (arguments.length > 1) {
second = Array.prototype.splice.call(arguments, 1, 1)[0];
for (var key in second) {
first[key] = second[key];
}
args = Array.prototype.slice.call(arguments, 0);
return extend.apply(this, args);
}
return first;
}
...
var briansDirections = {
step1: 'Remove pastry from wrapper.',
step2: 'Place pastry toaster.',
step3: 'Remove pastry from toaster and enjoy.',
};
extend(briansDirections, { step1: 'Toast Poptarts' }, { step2: 'Go ahead, toast \'em' }, { step3: 'Hey, are you sill reading this???' });
...
Це просто розширює сплеск предметів, рекурсивно. Також зауважте, що ця рекурсивна функція є TCO ( Tail-Call Optimized ), оскільки її повернення є останнім викликом до себе.
Крім того, ви можете захопити цільові властивості . У цьому випадку ви можете конденсувати об'єкти на основі id
,quantity
або інше майно. Цей підхід може писати про це невелику книгу, яка вимагає об'єктної супозиції та може отримати дуже складний характер. Я написав для цього невелику бібліотеку, яка доступна за запитом.
Сподіваюся, це допомагає!
У 2019 році у вас є 2 хороших варіанти:
Призначення об’єкта [ doc ]
const result = Object.assign({}, baseObject, updatingObject);
Поширення об’єктів [ doc ]
const result = { ...baseObject, ...updatingObject};
Перший має тенденцію бути більш безпечним, стандартним та багатовалентним. Хороші плюси і мінуси тут
Yahoo UI (YUI) також має допоміжну функцію для цього:
http://developer.yahoo.com/yui/examples/yahoo/yahoo_merge.html
YAHOO.namespace('example');
YAHOO.example.set1 = { foo : "foo" };
YAHOO.example.set2 = { foo : "BAR", bar : "bar" };
YAHOO.example.set3 = { foo : "FOO", baz : "BAZ" };
var Ye = YAHOO.example;
var merged = YAHOO.lang.merge(Ye.set1, Ye.set2, Ye.set3);
jquery має булеву форму для глибокої копії. Ви можете зробити щось подібне:
MergeRecursive = function(arr1, arr2){
$.extend(true, arr1, arr2);
return arr1;
};
Також ви можете редагувати цю функцію для підтримки n-масивів для злиття.
ArrayMergeRecursive = function(){
if(arguments.length < 2){
throw new Error("ArrayMergeRecursive: Please enter two or more objects to merge!");
}
var arr1=arguments[0];
for(var i=0; i<=arguments.length; i++ ){
$.extend(true, arr1, arguments[i]);
}
return arr1;
};
Так що тепер ви можете зробити
var arr1 = {'color': {'mycolor': 'red'}, 3: 5},
arr2 = {4: 10, 'color': {'favorite': 'green', 0: 'blue'}},
arr3 = ['Peter','Jhon','Demosthenes'],
results = ArrayMergeRecursive(arr1, arr2, arr3); // (arr1, arr2 ... arrN)
console.log("Result is:", results);
Мені було потрібно об'єднання глибоких об'єктів. Тож усі інші відповіді мені не дуже допомогли. _.extend і jQuery.extend справляються добре, якщо тільки у вас немає рекурсивного масиву, як я. Але це не так вже й погано, ви можете запрограмувати його на п’ять хвилин:
var deep_merge = function (arr1, arr2) {
jQuery.each(arr2, function (index, element) {
if (typeof arr1[index] === "object" && typeof element === "object") {
arr1[index] = deep_merge(arr1[index], element);
} else if (typeof arr1[index] === "array" && typeof element === "array") {
arr1[index] = arr1[index].concat(element);
} else {
arr1[index] = element;
}
});
return arr1;
}
Щоб об'єднати масиви в jQuery, що з $ .merge?
var merged = $.merge([{id:3, value:'foo3'}], [{id:1, value:'foo1'}, {id:2, value:'foo2'}]);
merged[0].id == 3;
merged[0].value == 'foo3';
merged[1].id == 1;
merged[1].value == 'foo1';
merged[2].id == 2;
merged[2].value == 'foo2';
var addProps = function (original, props) {
if(!props) {
return original;
}
if (Array.isArray(original)) {
original.map(function (e) {
return addProps(e, props)
});
return original;
}
if (!original) {
original = {};
}
for (var property in props) {
if (props.hasOwnProperty(property)) {
original[property] = props[property];
}
}
return original;
};
Тести
console.log(addProps([{a: 2}, {z: 'ciao'}], {timestamp: 13}));
console.log(addProps({single: true}, {timestamp: 13}));
console.log(addProps({}, {timestamp: 13}));
console.log(addProps(null, {timestamp: 13}));
[ { a: 2, timestamp: 13 }, { z: 'ciao', timestamp: 13 } ]
{ single: true, timestamp: 13 }
{ timestamp: 13 }
{ timestamp: 13 }
Object.getOwnPropertyNames is not a function
додаток перестане працювати.