1
\$\begingroup\$

I have the following snippet code which, within a loop, creates a JavaScript object where some of the properties maybe undefined:

reader.on('record', function(record) {

    let p = record.children;
    let player = {};

    // below we create a dynamic key using an object literal obj['name'], this allows use to use
    // the id as the firebase reference id.
    player[p[0].text] = {
        id: parseInt(p[0].text, 10) || "",
        name: p[1].text || "",
        country: p[2].text || ""
    };
};

My question therefore; is there a better way for creating this object via a 'Map' for example? If the properties are undefined then do not add them to the object.

Note: This data is being sent to a Firebase DB, so any undefined values throw an error -- my crude (but working) approach is to add them as an empty string.

Here is a sample of the JSON I would like to see (notice country is not missing from the second player):

{
 "players" : {
    "100001" : {
      "id" : 100001,
      "name" : "Matt Webb",
      "country" : "ENG"
    },
    "100002" : {
      "id" : 100002,
      "name" : "Joe Bloggs",
    }
}
\$\endgroup\$
  • \$\begingroup\$ Is this a code review question? It seems to me you have a question on the approach which is probably more suited for SO, as opposed to having the code you just want improved. Anyway, here is how I'd probably do it - you already have an array of values p, have another of keys that should match ["id", "name", "country"] and then just make a loop where you do something like if (p[i]) currentPlayer[keys[i]] = p[i]- then currentPlayer would only have the properties with values, the rest would be skipped. \$\endgroup\$ – VLAZ Jul 10 '16 at 18:46
  • \$\begingroup\$ Thanks @Vld I wasn't sure if it was for SO as my code is working, just needs to be refactoring! Thanks again. \$\endgroup\$ – Matt D. Webb Jul 10 '16 at 19:54
3
\$\begingroup\$

To make your code a bit more accurate you could run a function before every call to firebase (this is the main reason you need it) and create a new object with only defined props

function getDefinedProps(obj) {
  var o = {}
  for (key in obj) {
    if (obj[key] !== undefined)
      o[key] = obj[key]
  }

  return o;
}
\$\endgroup\$
  • \$\begingroup\$ Just a note - this is a pure function but this is also doable as a an impure one that directly changes the passed in parameter. Instead of creating a new object and copying the properties, the body of the if statement can be changed to delete obj[key]. I'd personally prefer the pure approach in this answer, but sometimes you may want to run "modify in place", in which case an impure variant can be useful. \$\endgroup\$ – VLAZ Jul 11 '16 at 13:23
  • 1
    \$\begingroup\$ @Vld you are absolutely right, this is a pure function. I first wanted to make it with delete like you mentioned. But decided to go without manipulating the original object, because it might be helpful to have the raw version of the unfixed object locally.. for what ever reasons. Manipulation an object in place can produce unexpected behavior for the UI, this pure function should be thought like a middleware before sending the data to firebase \$\endgroup\$ – webdeb Jul 11 '16 at 13:52
2
\$\begingroup\$

JSON.stringify() seems to do exactly what you need.

It will remove all functions and all undefined variables.

a = { b : undefined , c : 'inited'};
JSON.stringify( a )

will return

'{"c":"inited"}'

If you need the object itself, you can JSON.parse the resulting string to go back to a clean object.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.