Object assign with countable keys


#1

Hi,

Im building an offline sync for an Ionic 2 application.
When there is no internet connection i’ve to add it to the current JSON (Objects).

Under here example code and the console.log output what happens.

        // Projects object
		var oStreetById = this.getStreetHousesById(iProjectId, iStreetId, iHouseId);

		// Nieuwe counter
		var iCounter = Math.floor((Math.random()*6)+1);

		// Data opbouwen voor de afbeeldingen met elementen
		let oAddHouseObject = {
			 iCounter : {
				'_id'					: 	'app-'+ iRandom,
				'activities' 			:   null,
				'floor' 				: 	oHouseObject.object.floor,
				'height' 				:   '0',
				'note'					:  	oHouseObject.object.note,
				'side'					: 	oHouseObject.object.side,
				'url'					:   oHouseObject.object.picture,
				'width'					:	'0'
			}
		};

		// Huis ophalen vanuit iHouseId
		Object.assign(oStreetById, oAddHouseObject);

What happens in this piece of code is building an new Object to assign it to the main object so it will be visible for offline use.

But what really happens

0
:
{id: "590", width: "133", height: "200", side: "Voorzijde", …}
1
:
{id: "595", width: "133", height: "200", side: "Zijgevel", …}
iCounter
:
{_id: "app-504702", activities: null, floor: 4, height: "0", note: "", …}

iCounter has to been an random number, but iCounter is being readed as the key while it’s a variable at this place:

let oAddHouseObject = {
			 **iCounter** : {
				'_id'					: 	'app-'+ iRandom,
				'activities' 			:   null,
				'floor' 				: 	oHouseObject.object.floor,
				'height' 				:   '0',
				'note'					:  	oHouseObject.object.note,
				'side'					: 	oHouseObject.object.side,
				'url'					:   oHouseObject.object.picture,
				'width'					:	'0'
			}
		};

(Highlighted as iCounter)

Hope some one can help me out with this.

Thanks in advance


#2

This thread is perhaps relevant.


#3

As already mentioned, never use var. Always use const or let. Beyond that, I use Object.assign a lot, but I wouldn’t use it here, because your objects have too much nesting, and Object.assign only makes shallow copies. I think you should make a deepCopyAddHouseObject method, and inside that method make sure you are deep copying every piece of the object, and piecing together a completely new object. Your code right now is leaving open the possibility of weird errors, because when you modify one object, you’re actually modifying a lot of them.


#4

It’s not relevant on this topic, by changes var to let will not change anything for me.

// Nieuwe counter
		let iCounter = Math.floor((Math.random()*6)+1);

		// Data opbouwen voor de afbeeldingen met elementen
		let oAddHouseObject = {
			 iCounter : {
				'_id'					: 	'app-'+ iRandom,
				'activities' 			:   null,
				'floor' 				: 	oHouseObject.object.floor,
				'height' 				:   '0',
				'note'					:  	oHouseObject.object.note,
				'side'					: 	oHouseObject.object.side,
				'url'					:   oHouseObject.object.picture,
				'width'					:	'0'
			}
		};

iCounter inside that Object will be iCounter instead of example 2159219.
That’s the problem what I got at this moment.


#5

Thanks for your answer.
Yes, I already got multiple functions to build up the nested objects, Got an own provider for it to do.
Everything is splitted up and well organized, but called above is the problem that I have,


#6
oAddHouseObject[iCounter]={
		'_id'					: 	'app-'+ iRandom,
		'activities' 			:   oActivities,
		'floor' 				: 	oHouseObject.object.floor,
		'height' 				:   '0',
		'note'					:  	oHouseObject.object.note,
		'side'					: 	oHouseObject.object.side,
		'url'					:   oHouseObject.object.picture,
		'width'					:	'0'
	}

#7

Im creating an object inside an object.
See the example.

let oAddHouseObject = {
			 iCounter : {
				'_id'					: 	'app-'+ iRandom,
				'activities' 			:   oActivities,
				'floor' 				: 	oHouseObject.object.floor,
				'height' 				:   '0',
				'note'					:  	oHouseObject.object.note,
				'side'					: 	oHouseObject.object.side,
				'url'					:   oHouseObject.object.picture,
				'width'					:	'0'
			}
		};

#8

He’s suggesting a cleaner way to do it. Personally, I would use a Map from immutable.js, get the counter out from inside the object and use it as a key for the houseobject value. Either a Map or an Array would eliminate one level of object nesting, and have the added benefit of being Iterable.


#9

@wthijmen You can assign a dynamic value as the property name like the following:

let oAddHouseObject = {
	[iCounter]: {
		'_id'					: 	'app-'+ iRandom,
		'activities' 			:   oActivities,
		'floor' 				: 	oHouseObject.object.floor,
		'height' 				:   '0',
		'note'					:  	oHouseObject.object.note,
		'side'					: 	oHouseObject.object.side,
		'url'					:   oHouseObject.object.picture,
		'width'					:	'0'
	}
};

Or like @Tommertom said, you can assign it like:

oAddHouseObject[iCounter]={ … your stuff…}

But anyway, Object.assign() seems a bit off, I think it’s better to revise your code, but the above solution should work.


#10

Object.assign only works at one level. All nested objects will still be aliased. You could use something like lodash’s clonedeep instead.