Reputation: 1131
What I am trying to do I am trying to deeply re-map an existing array of objects using a mapping function. The mapping it self works as you can see in "output 1" below, but the deep assignment of the object is not working, which means, it is not taking place (see "output 2").
(Background) less important info: (Due to the 'deep population' constraint in waterline (sailsJS), i am trying to do the population manually using async's auto)
code:
var roomsMapper = _.indexBy(results.rooms, 'id'); // maps id to a new room object that has array of children
_.each(data.centers, function (center, index) {
var mappedRooms = _.map(center.rooms, function (room) {
return roomsMapper[room.id];
});
sails.log.info("mappedRooms: ", mappedRooms); // as expected see output 1
data.centers[index].rooms = mappedRooms;
sails.log.info("data.centers[index]: ", data.centers[index]); // not as expected, see output 2
});
sails.log.info("data.centers: ", data.centers); // new values are not assigned
output1 (the mapped value has array of children):
info: mappedRooms: [ { children:
[ { name: 'Child Khoury',
birthday: Sun Dec 28 2008 00:00:00 GMT+0200 (Jerusalem Standard Time),
sex: 'M',
allergies: null,
id: '53dff26a3e5cb1b01f2f2e13',
createdAt: Mon Aug 04 2014 23:51:54 GMT+0300 (Jerusalem Summer Time),
updatedAt: Mon Aug 04 2014 23:51:54 GMT+0300 (Jerusalem Summer Time),
room: '53dff0205c89c03428a31cf0' },
{ name: 'Ashqar Sameeh',
birthday: Tue Feb 01 2000 00:00:00 GMT+0200 (Jerusalem Standard Time),
sex: 'F',
allergies: null,
id: '53dff2803e5cb1b01f2f2e14',
createdAt: Mon Aug 04 2014 23:52:16 GMT+0300 (Jerusalem Summer Time),
updatedAt: Mon Aug 04 2014 23:52:16 GMT+0300 (Jerusalem Summer Time),
room: '53dff0205c89c03428a31cf0' } ],
center: '53dff0205c89c03428a31cee',
name: 'sydney room2',
min_age: 5,
max_age: 7,
createdAt: Mon Aug 04 2014 23:42:08 GMT+0300 (Jerusalem Summer Time),
updatedAt: Mon Aug 04 2014 23:42:08 GMT+0300 (Jerusalem Summer Time),
id: '53dff0205c89c03428a31cf0' },
{ children:
[ { name: 'Samih Samama',
birthday: Mon Dec 29 2008 00:00:00 GMT+0200 (Jerusalem Standard Time),
sex: 'M',
allergies: [Object],
id: '53dff29e3e5cb1b01f2f2e16',
createdAt: Mon Aug 04 2014 23:52:46 GMT+0300 (Jerusalem Summer Time),
updatedAt: Mon Aug 04 2014 23:52:46 GMT+0300 (Jerusalem Summer Time),
room: '53dff0205c89c03428a31cef' } ],
center: '53dff0205c89c03428a31cee',
name: 'sydney room1',
min_age: 0,
max_age: 3,
createdAt: Mon Aug 04 2014 23:42:08 GMT+0300 (Jerusalem Summer Time),
updatedAt: Mon Aug 04 2014 23:42:08 GMT+0300 (Jerusalem Summer Time),
id: '53dff0205c89c03428a31cef' } ]
output2 (mappedRooms is not assigned- children array is missing):
info: data.centers[index]: { rooms:
[ { name: 'sydney room2',
center: '53dff0205c89c03428a31cee',
min_age: 5,
max_age: 7,
createdAt: Mon Aug 04 2014 23:42:08 GMT+0300 (Jerusalem Summer Time),
updatedAt: Mon Aug 04 2014 23:42:08 GMT+0300 (Jerusalem Summer Time),
id: '53dff0205c89c03428a31cf0' },
{ name: 'sydney room1',
center: '53dff0205c89c03428a31cee',
min_age: 0,
max_age: 3,
createdAt: Mon Aug 04 2014 23:42:08 GMT+0300 (Jerusalem Summer Time),
updatedAt: Mon Aug 04 2014 23:42:08 GMT+0300 (Jerusalem Summer Time),
id: '53dff0205c89c03428a31cef' } ],
state: '53df76c278999310248072c6',
name: 'Sydney Center',
menuItems: null,
createdAt: Mon Aug 04 2014 23:42:08 GMT+0300 (Jerusalem Summer Time),
updatedAt: Mon Aug 04 2014 23:42:08 GMT+0300 (Jerusalem Summer Time),
id: '53dff0205c89c03428a31cee' }
Upvotes: 0
Views: 196
Reputation: 76
I tried it, could not really get it why when you pass center to the map callback function and modify one of its properties somehow the reference is lost.
Anyway, the following worked for me:
var roomsMapper = _.indexBy(results.rooms, 'id');
var mappedCenters = _.map(data.centers, function (center) {
var _center = center.toObject(); // create new object
_center.rooms = _.map(center.rooms, function (room) {
return roomsMapper[room.id];
});
return _center;
});
Upvotes: 1
Reputation: 579
Object assignment is by reference, not by value. I use the following to copy one object into another:
function extendObject(destination, source) {
for (var property in source) {
if (source[property] && source[property].constructor &&
source[property].constructor === Object) {
destination[property] = destination[property] || {};
arguments.callee(destination[property], source[property]);
} else {
destination[property] = source[property];
}
}
return destination;
};
So, as an example:
var obj1 = { a: { foo: 'bar' } };
var obj2 = { b: { bar: 'foo' } };
extendObject(obj2, obj1);
obj1.a.foo = "different";
console.log(obj1);
console.log(obj2);
Would output:
{ a: { foo: 'different' } }
{ b: { bar: 'foo' }, a: { foo: 'bar' } }
[Edit] - If I'm understanding the problem correctly, this would essentially do the same thing:
var roomsMapper = _.indexBy(results.rooms, 'id');
_.each(data.centers, function (center, index) {
var mappedRooms = [];
for( i in center.rooms ) {
mappedRooms.push(roomsMapper[center.rooms[i].id]);
}
data.centers[index].rooms = mappedRooms;
});
Upvotes: 1