Lord Elrond
Lord Elrond

Reputation: 16032

Error: cannot read property push of undefined when using .push on an empty array that is stored in an object

When a user clicks "save" I need to collect all the data from inputs with a class of input_product and compile it to data with this format:

data = {param1:[{upc:'upc', value:'value'}, ... ], ... paramN: [ ... ]}


I tried doing this with the code below, but I keep getting this error:

Uncaught TypeError: Cannot read property 'push' of undefined

$('.save').on('click', function() {
  event.preventDefault();
  var data = {};

  $('.input_product').each(function() {

    const
    param = $(this).attr('name'),
    upc = $(this).parent().parent().attr('id'),
    value = $(this).val()

    console.log(param, upc, value); //prints qty, 1001, 5

    if (value && param) {
       if (!param in data) {
           data[param] = [];
       }
       data[param].push({'upc':upc, 'value':value}); // Error is thrown here
    }
  });
 window.someFunction(data);
});

What am I missing here?

Upvotes: 1

Views: 287

Answers (1)

Unmitigated
Unmitigated

Reputation: 89294

The in operator has lower precedence than the ! operator. You need to add brackets around param in data; change

if(!param in data)

to

if(!(param in data))

Currently, what you are doing is converting the value of param to a boolean, negating that, and then checking if the result of that negation exists as a key in the object data (i.e., what you are writing is equivalent to if((!param) in data)) , when instead you want to check if param exists as a key in data and then negate the result of that to execute some code if param does not exist as a key in data. As a result, you are never setting the value of the key param in data, so it stays at undefined and you get the Uncaught TypeError: Cannot read property 'push' of undefined.

See Operator Precedence.

Try this:

$('.save').on('click', function() {
  event.preventDefault();
  var data = {};

  $('.input_product').each(function() {

    const
    param = $(this).attr('name'),
    upc = $(this).parent().parent().attr('id'),
    value = $(this).val()

    console.log(param, upc, value);

    if (value && param) {
       if (!(param in data)) {//added brackets
           data[param] = [];
       }
       data[param].push({'upc':upc, 'value':value}); 
    }
  });
 window.someFunction(data);
});

Working JSFiddle Demo: https://jsfiddle.net/n6bg3da8/

Upvotes: 3

Related Questions