0

i want to pull data from a .csv file and pass this data to a function to format every row of the .csv file to be a single object. These objects are then stored in an array called "list". So far so good. This is all working.

Next i want a button that calls a function onclick called "roll" that takes a random index from the "list" array and saves an instance of the random oject in a temporarily variable called randomItem.

Then i want to check certain properties of randomItem for specific values and if a certain condition is met it should change a specific property called "randomItem.Name". Finally i want the altered "randomItem" to be pushed into a new array called "results". These results are then being displayed on the website.

If I change the propertys value with "randomItem.Name = randomItem.Name + 'someString'" it also overwrites the original object in the "list" array. I dont want it to do this as i want to repeat the process of rolling random objects from this list several times. Therefor i need the "list" array to keep its original state. I cant get my head around why it overwrites the any list.

html <button id="btnItem1">Roll</button>

js

$(document).ready(function() {

    let list = [];
    let results = [];    

    $('#btnItem1').click({slotName:'item1', listName:list, index:0}, roll);
// i need to pass slotName, listName and index because i have several buttons and list in the real project
    
    getData('data.csv').then(data => formatData(data)); // get data from csv files

    async function getData(url) {
        const response = await fetch(url);
        const data = await response.text();
        return data; 
    };

    function formatData(data) { // real formatting function taken out for stackflow
    
        let formatted = // some formatting stuff;
        list.push(formatted);

    }; 

    function roll(options) {
        const slot = options.data.slotName;
        const listTemp = options.data.listName;
        const index = options.data.index;

        if (slot.includes('item')) { // real criteria taken out for stackflow
            do {
                const randomNumber = Math.floor(Math.random() * (listTemp.length - 1) + 1);
                let randomItem = listTemp[randomNumber];

                if (1 == 1) { // real criteria taken out for stackflow

                    let chance = Math.round(Math.random());
                         
                    if (chance) {
                        randomItem.Name += '(altered)';
                    }  
                }

                results.splice(index, 1, randomItem);

            } while (1 != 1); // real criteria taken out for stackflow

        };
    };
});

I expect it to write the altered "randomItem.Name" only to randomItem itself. Not even to listTemp but definitly not to the global "list". Do you have any idea why it is doing this and how i can prevent this? How can i get the object into randomItem without randomItem keeping its reference to any list. Thank you guys in advance!

Daniel B.
  • 1
  • 1
  • 2
    Hi, It's the concept of passByValue and passByRefernce. You can get more details here: https://stackoverflow.com/questions/518000/is-javascript-a-pass-by-reference-or-pass-by-value-language – Yash Maheshwari May 06 '21 at 14:49
  • Try `let randomItem = JSON.parse(JSON.stringify(listTemp[randomNumber]));`. This should copy the object instead of storing its reference. – Nisala May 06 '21 at 15:02
  • Thank you both so much. JSON.stringify seems to work. Is this a valid workaround or nasty code? It feels kinda unlogic to convert an object to a string and then back again into an object only to loose its reference. – Daniel B. May 06 '21 at 15:22
  • It’s definitely an accepted way to do it in the JS community. https://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-deep-clone-an-object-in-javascript – Nisala May 06 '21 at 18:55

0 Answers0