TypeError: Assignment to constant variable, when trying to create an array of objects

I’ve been working on a scraper and all was good until I’ve tried to push objects of scraped data into an array.

Right now I have this:

exports.parseData = (getLink, getDescription, getPrice, getPicture) => {
  const apartments = [];
  apartments = {
    link: getLink,
    descr: getDescription,
    price: getPrice,
    picture: getPicture,
  };
  console.log(apartments);
};

But it throws an error: TypeError: Assignment to constant variable.

Now I think this is happening because of how data is sent to a parser.
Here is how data looks when I use this code:

exports.parseData = (getLink, getDescription, getPrice, getPicture) => {
  console.log(getLink);
  console.log(getDescription);
  console.log(getPrice);
  console.log(getPicture);
  console.log('-----------------');
};


https://www.sant.ba/nekretnine/nekretnina-3467-dvosoban-stan-sa-liftom-u-samom-centru-grada-63-m2
 dvosoban stan sa liftom u samom centru grada , 63 m2 
199000.00
https://www.sant.ba/thumb.php?file=photos/3467/3467_1_1563271355.jpg&maxw=273&maxh=205
-----------------
https://www.sant.ba/nekretnine/nekretnina-3689-troiposoban-stan-u-naselju-sunca
 Troiposoban stan u naselju Sunca
360000.00
https://www.sant.ba/thumb.php?file=photos/3689/3689_1_1612344465.jpg&maxw=273&maxh=205
-----------------
https://www.sant.ba/nekretnine/nekretnina-3677-trosoban-renoviran-stan-u-naselju-dolac-malta-73-m2
 trosoban, renoviran stan u naselju Dolac malta, 73 m2
150000.00
https://www.sant.ba/thumb.php?file=photos/3677/3677_1_1608550332.jpg&maxw=273&maxh=205
-----------------
https://www.sant.ba/nekretnine/nekretnina-3537-cetverosoban-stan-u-novogradnji-sa-prelijepim-pogledom-na-grad-118-38-m2
 Četverosoban stan u novogradnji sa prelijepim pogledom na grad, 118,38 m2 
538090.37
https://www.sant.ba/thumb.php?file=photos/3537/3537_1_1573217155.jpg&maxw=273&maxh=205
-----------------
https://www.sant.ba/nekretnine/nekretnina-3536-trosoban-stan-u-novogradnji-sa-prelijepim-pogledom-na-grad-105-34-m2
 Trosoban stan u novogradnji sa prelijepim pogledom na grad, 105,34 m2
478817.70
https://www.sant.ba/thumb.php?file=photos/3536/3536_2_1573216638.jpg&maxw=273&maxh=205
-----------------
https://www.sant.ba/nekretnine/nekretnina-3535-luksuzni-cetverosoban-stan-na-cobaniji-117-43m2
 Luksuzni četverosoban stan na Čobaniji,117,43m2
533772.19
https://www.sant.ba/thumb.php?file=photos/3535/3535_13_1573215220.jpg&maxw=273&maxh=205
-----------------
https://www.sant.ba/nekretnine/nekretnina-3534-trosoban-stan-u-novogradnji-90-m2
 trosoban stan u novogradnji, 90 m2
376923.46
https://www.sant.ba/thumb.php?file=photos/3534/3534_8_1573214216.jpg&maxw=273&maxh=205
-----------------
etc....

Now what my desired output would be: To have an array of objects, where objects are filled with data like it’s shown in example above. So for each getLink, getDescription, getPrice, getPicture create new object and push it into an array(like I’m using it in the first code block).

Output that I would like to get is:

[
   {
   
      link: https://www.sant.ba/nekretnine/nekretnina-3467-dvosoban-stan-sa-liftom-u-samom-centru-grada-63-m2
      descr: dvosoban stan sa liftom u samom centru grada , 63 m2 
      price: 199000.00
       picture: https://www.sant.ba/thumb.php?file=photos/3467/3467_1_1563271355.jpg&maxw=273&maxh=205
   },
   {
     link:https://www.sant.ba/nekretnine/nekretnina-3689-troiposoban-stan-u-naselju-sunca
     descr: Troiposoban stan u naselju Sunca
     price: 360000.00
     picture: https://www.sant.ba/thumb.php?file=photos/3689/3689_1_1612344465.jpg&maxw=273&maxh=205
   },
   etc...
]

Is something like this easy to achieve?
Thanks!

Here is from where these variables are sent:

const cheerio = require('cheerio');
const axios = require('axios');
const parsing = require('./parseData');

exports.olxScraper = () => {
  const url =
    'https://www.olx.ba/pretraga?vrsta=samoprodaja&kategorija=23&sort_order=desc&kanton=9&sacijenom=sacijenom&stranica=1';

  const getRawData = async () => {
    try {
      await axios.get(url).then((res) => {
        const $ = cheerio.load(res.data);
        $('div[id="rezultatipretrage"] > div')
          .not('div[class="listitem artikal obicniArtikal  i index"]')
          .not('div[class="obicniArtikal"]')
          .each((index, element) => {
            $('span[class="prekrizenacijena"]').remove();
            const getLink = $(element)
              .find('div[class="naslov"] > a')
              .attr('href');
            const getDescription = $(element)
              .find('div[class="naslov"] > a > p')
              .text();
            const getPrice = $(element)
              .find('div[class="datum"] > span')
              .text()
              .replace(/\.| ?KM$/g, '')
              .replace(' ', '');
            const getPicture = $(element)
              .find('div[class="slika"] > img')
              .attr('src');

            parsing.parseData(getLink, getDescription, getPrice, getPicture);
          });
      });
    } catch (error) {
      console.log(error);
    }
  };
  getRawData();
};

exports.santScraper = () => {
  const url = `https://www.sant.ba/pretraga/prodaja-1/tip-2/cijena_min-20000/stranica-1`;

  const getRawData = async () => {
    try {
      await axios.get(url).then((response) => {
        const $ = cheerio.load(response.data);

        $('div[class="col-xxs-12 col-xss-6 col-xs-6 col-sm-6 col-lg-4"]').each(
          (index, element) => {
            const getLink = $(element).find('a[class="re-image"]').attr('href');
            const getDescription = $(element).find('a[class="title"]').text();
            const getPrice = $(element)
              .find('div[class="prices"] > h3[class="price"]')
              .text()
              .replace(/\.| ?KM$/g, '')
              .replace(',', '.');
            const getPicture = $(element).find('img').attr('data-original');
            /*const getSquaremeters = $(element)
        .find('span[class="infoCount"]')
        .first()
        .text()
        .replace(',', '.')
        .split('m')[0];

      const pricepersquaremeter =
        parseFloat(getPrice) / parseFloat(getSquaremeters);
      articles[index] = {
        id: getLink.substring(42, 46),
        link: getLink,
        descr: getDescription,
        price: Math.round(getPrice),
        pictures: getPicture,
        sqm: Math.round(getSquaremeters),
        ppm2: Math.round(pricepersquaremeter),
      };*/
            parsing.parseData(getLink, getDescription, getPrice, getPicture);
          }
        );
      });
    } catch (error) {
      console.log(console.log(error));
    }
  };
  getRawData();
};

this.olxScraper();
this.santScraper();

24 thoughts on “TypeError: Assignment to constant variable, when trying to create an array of objects”

  1. You are declaring apartments with const.

    const apartments = [];
    

    So it’s been set as an array. But then you are then trying to change it to an object.

    apartments = {
        link: getLink,
        descr: getDescription,
        price: getPrice,
        picture: getPicture,
      };
    

    Consts cannot be updated or declared. Once you have declared it as an array. it can only stay as an array. You can push to that array but you cannot change it to an object or any other data type.

    In your case, you could just declare the const apartments as an object straight away.

    const apartments = {
        link: getLink,
        descr: getDescription,
        price: getPrice,
        picture: getPicture,
      };
    

    You can read more about var, let and const here: https://www.freecodecamp.org/news/var-let-and-const-whats-the-difference/

    adding an example based on the comments.

    const data = [];
    
    const parseData = (getLink, getDescription, getPrice, getPicture) => {
        const apartments = {
            link: getLink,
            descr: getDescription,
            price: getPrice,
            picture: getPicture,
          };
        data.push(apartments)
        console.log(data);
    };
    

    data is not scoped to the parseData function, and can therefore contain all the apartments objects, that get pushed to it. Where this data array should be declared depends very much on your code, and should probably be passed to the parseData function as an argument as well.

    Reply
  2. There are more than just one issue with your code:

    1. You can’t reassign a const variable.

       const apartments = [];
       apartments = { ... };  //this is not allowed, becasue apartments is const.
      
    2. You define apartments as an array, and then try to assign an object to that same variable. That’s allowed in javascript, but probably not what you want …

    EDIT

    As for your comment: If you want a single array to contain all your objects, you must define your array outside of your function and define your parseData function to return an object, which then can be pushed into that array.

    const apartments = [];
    const getRawData = async () => {
        try {
          await axios.get(url).then((res) => {
            const $ = cheerio.load(res.data);
            $('div[id="rezultatipretrage"] > div')
              .not('div[class="listitem artikal obicniArtikal  i index"]')
              .not('div[class="obicniArtikal"]')
              .each((index, element) => {
                $('span[class="prekrizenacijena"]').remove();
                const getLink = $(element)
                  .find('div[class="naslov"] > a')
                  .attr('href');
    
                ....
    
                //push the result of parseData into the array
                apartments.push(parsing.parseData(getLink, getDescription, getPrice, getPicture));
    
    
               //if your parsedata just returns an object created from its parameters,
               //you can get rid of the function and just do 
               //apartments.push({
               //  link: getLink,
               //  descr: getDescription,
               //  price: getPrice,
               //  picture: getPicture           
               //});
              });
          });
        } catch (error) {
          console.log(error);
        }
      };
    

    Redefine parseData to just return an object. Although it seems quite unnecessary, to have a function which just returns an object of its parameters.

    exports.parseData = (getLink, getDescription, getPrice, getPicture) => {
      const apartment = {
        link: getLink,
        descr: getDescription,
        price: getPrice,
        picture: getPicture,
      };
      return apartment;
    };
    
    Reply
  3. When you declare a constant, the reference cannot be changed. In your code it says const apartments = [], so you declare const as an array and later try to declare const as an object.

    Try

    apartments.push({
        link: getLink,
        descr: getDescription,
        price: getPrice,
        picture: getPicture,
      });
    
    Reply
  4. What I see is that you assigned the variable apartments as an array and declared it as a constant. Then, you tried to reassign the variable to an object.

    When you assign the variable as a const array and try to change it to an object, you are actually changing the reference to the variable, which is not allowed using const.

    const apartments = [];
      apartments = {
        link: getLink,
        descr: getDescription,
        price: getPrice,
        picture: getPicture,
      };
    

    The options I see as simplest are to push the object into the array:

    apartments.push({
        link: getLink,
        descr: getDescription,
        price: getPrice,
        picture: getPicture,
      });
    

    Or to assign the object to a variable always when you are about to push to the array:

    const apartments = [];
    let apartment = {
        link: getLink,
        descr: getDescription,
        price: getPrice,
        picture: getPicture,
      };
    
    apartments.push(apartment);
    
    Reply

Leave a Comment