2

I'm doing the following code in javascript:

 var res = [{}];
    for (var idx = 0; idx < json.length; idx++) {
        // if the environment is already entered in the result
        if (res[idx].env) {
            sails.log.debug('Environment is in result');
            // if the current inspected value has been deployed later than the stored one
            if (res[idx].updatedAt < json[idx].updatedAt) {
                sails.log.debug('Updating the value in the result');
                //res[json[idx].lifeCycle] = JSON.parse('{"'+json[idx].version+'":"'+json[idx].updatedAt+'"}');
                res.env = json[idx].lifeCycle;
                res.ver = json[idx].version;
                res.updatedAt = json[idx].updatedAt;
            }
        } else {
            // it is the first time we are adding to the result the component version (for the given environment)
            if (json[idx].lifeCycle) {
                //add the value in result
                res[idx].env = json[idx].lifeCycle || '';
                res[idx].ver = json[idx].version || '';
                res[idx].updatedAt = json[idx].updatedAt || '';
            }
            else {
                sails.log.debug('Lifecycle is null or empty');
            }
        }
    }
    return res;

This code receives a JSON with more than 1 element in it that has many values. After doing my checks, it goes to the bottom line where it says

if (json[idx].lifeCycle) {
                //add the value in result
                res[idx].env = json[idx].lifeCycle || '';
                res[idx].ver = json[idx].version || '';
                res[idx].updatedAt = json[idx].updatedAt || '';
            }

In here, IDX is equals to 1 (second time coming around the for loop).

When I try to insert the second value to "res", i get error:

TypeError: Cannot read property 'env' of undefined

It's as if res didn't exist anymore after doing the first pass through the for loop.

Can anyone help me out and lemme know why this is happening?

Thanks so much!

Liquidice
  • 175
  • 1
  • 11
  • did you tried by putting a debugger in the else block. You would be able to see if res exists during the for loop execution. It might not totally answer your question but might help you better understand the problem – Sumit Surana May 25 '17 at 09:03
  • please add the object/s as well. – Nina Scholz May 25 '17 at 09:03
  • 1
    *"...into an array of jsons"* JSON is a *textual notation* for data exchange. [(More here.)](http://stackoverflow.com/a/2904181/157247) If you're dealing with JavaScript source code, and not dealing with a *string*, you're not dealing with JSON. – T.J. Crowder May 25 '17 at 09:04
  • There's no JSON in your question. `json` in your question is an array of objects. `res.env` in the `if (res[idx].env) { ... }` branch looks at least suspicious. [How to create a Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve) – Andreas May 25 '17 at 09:05

1 Answers1

2

Well if you look at your res array, it only has a single element, which is an empty object. so it means that :

res[0] // -> {}

and

res[1] // -> undefined

Simple solution (the one that changes your code the least)

You just need to create a new object when trying to access the res[idx] element in the array.

Your code would look like this

if (json[idx].lifeCycle) {
  res[idx] = res[idx] || {}; // if the index `idx` is not set, just init it to an empty object
  res[idx].env = json[idx].lifeCycle || '';
  res[idx].ver = json[idx].version || '';
  res[idx].updatedAt = json[idx].updatedAt || '';
}

Slightly better solution

Or you could even simplify a bit that code and create a new object at every loop and push it into your res array. If you do this, you will also have to init the res array to an empty array var res = []:

if (json[idx].lifeCycle) {
  res.push({
    env: json[idx].lifeCycle || '',
    ver: json[idx].version || '',
    updatedAt: json[idx].updatedAt || ''
  })
}

This way, you don't need to handle special case if you have an element in the array or not, you just treat every single loop the same

Best solution (IMO): functional programming FTW

Not sure if you are aware of array function like Array.prototype.map. This is a function that allow you to map a function on every single element of an array, an transform it into a transformed element. It creates a new array composed of the transformed elements.

Here is what the code would look like with the fabulous map method:

var res = json
    .map(function (element) {
      return {
        env: json[idx].lifeCycle || '',
        ver: json[idx].version || '',
        updatedAt: json[idx].updatedAt || ''
      }
    });

If I am correct in res you will have the same values as what you code produces.

I removed the first condition if (res[idx].env) which I think is never true because res[idx] will either be undefined or an empty object (but I might be wrong on this one).

Anyway, if you find this solution cool, be sure to check the documentation on map, filter and reduce on the MDN :) https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/map

atomrc
  • 2,543
  • 1
  • 16
  • 20
  • This worked! Thanks so much. putting res[idx] = res[idx] || {}; worked. – Liquidice May 25 '17 at 09:35
  • My pleasure. BTW I just added a new simpler solution that you might want to check if you are curious and want to try new way of doing things :) Let me know if you enjoyed this last solution – atomrc May 25 '17 at 09:44
  • Yup, works like a charm, your latest one was "cleaner". Thank you! – Liquidice May 25 '17 at 13:59