0

I have this piece of code, but whenever I run findTimeSlots() it immediately messes up my global array apptData but I don't see in anywhere in this function that is supposed to have changed it.

(ConsoleLog)

(index):69 
(4) [{…}, {…}, {…}, {…}]
0: {service: "A, B", duration: 50, tech: "C"}
1: {service: "B", duration: 30, tech: "C"}
2: {service: "A, D", duration: 60, tech: "A"}
3: {service: "D", duration: 40, tech: "A"}
length: 4
__proto__: Array(0)
(index):45 
(4) [{…}, {…}, {…}, {…}]
0: {service: "A, B", duration: 50, tech: "C"}
1: {service: "B", duration: 30, tech: "C"}
2: {service: "A, D", duration: 60, tech: "A"}
3: {service: "D", duration: 40, tech: "A"}
length: 4
__proto__: Array(0)

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

var apptData = [];
function addApptData(serviceName, rawDuration, selectedTech){
    apptData.push({
        'service': serviceName,
        'duration': rawDuration,
        'tech' : selectedTech
    })
}
function reduceApptData(index){
    apptData.splice(index, 1);
}
function findTimeSlots(dateStr){
    console.log(apptData);             //* Index 45 *//
    var final = new Array();
    var service, duration;
    for(var i = 0; i < apptData.length; i++){
        var duplicated = false;
        for(var j = 0; j < final.length; j++){
            if(final[j].tech == apptData[i].tech){
                service = ", "+apptData[i].service;
                final[j].service += service;
                duration = apptData[i].duration;
                final[j].duration += duration;
                duplicated = true;
                break;
            }
        }
        if(!duplicated){
            final.push(apptData[i]);
        }
    }
 }
addApptData("A", 20, "C");
addApptData("B", 30, "C");
addApptData("A", 20, "A");
addApptData("D", 40, "A");
console.log(apptData);                //* Index 69 *//
// If I remove the line below, I get the expected result, when I try to 
// run with this line it will mess up apptData[]
findTimeSlots("");

What I expected to be is

0: {service: "A", duration: 20, tech: "C"}
1: {service: "B", duration: 30, tech: "C"}
2: {service: "A", duration: 20, tech: "A"}
3: {service: "D", duration: 40, tech: "A"}
length: 4
__proto__: Array(0)

So basically I expect it to remain the same.

I wanted to consolidate my var apptData into my var final inside my findTimeSlots()

After debugging, I found out that my apptData keep changing unexpectedly for some reason.

I suspect this to be very trivial but I cannot for the life of me figure out.

4
  • That's why I love FP and it's immutability. Commented Apr 5, 2019 at 2:17
  • 2
    final.push(apptData[i]) pushes an object without copying it, final[j].service += service; and final[j].duration += duration; modify objects that were pushed. Commented Apr 5, 2019 at 2:22
  • 2
    When you assign objects in JavaScript you're not making a copy, you're just assigning a reference to the same object. So when findTimeSlots() modifies final[j].property, it's also modifying apptData. Commented Apr 5, 2019 at 2:22
  • See stackoverflow.com/questions/728360/… for ways to clone a JavaScript object. Commented Apr 5, 2019 at 2:23

3 Answers 3

1

What is happening is explained in this tiny example:

let a = {test: 10};
let b = a;
b.text = 11;
console.log(a); //this will print {test: 11}

Since a is an object, when you assign let b = a; you are actually saving a reference to a, not cloning a.

You need to clone the object apptData[i], and to do that See this answer

So instead of final.push(apptData[i]); you should push a cloned apptData[i].

Hope that helps.

Sign up to request clarification or add additional context in comments.

Comments

1

You should make a shallow copy of apptData.

One thing you should take note of JavaScript is the difference between assignment by value vs assingment by reference.

When primitive data types such as numbers(i.e. 2, 23), strings (i.e 'aaa', '123') are assigned to a variable, the variable contains the primitive value.

On the other hand, when non-primitive data types (arrays, objects, functions) are assigned to a variable, the variable contains the reference (which 'points' to the object's location on the memory), rather than the value itself.

To answer your question, you should be making a shallow copy of apptData, rather than making a direct reference to it.

Assuming that your apptData is an array of (non-nested) objects, here is a simply way to make a shallow copy of it using ES6's spread syntax:

const apptDataCopy = apptData.map(serviceObject => ({...serviceObject}));

From there, you can make any changes you wish to apptDataCopy, and it will not affect the original apptData.

Comments

1
var apptData = [], typeSelectedTech = new Set(), finalData =[], tmpObj = {serviceName: '', rawDuration: 0}
const addApptData = (serviceName, rawDuration, selectedTech)=> {
    apptData.push({
        serviceName,
        rawDuration,
        selectedTech
    })
    if (typeSelectedTech.has(selectedTech)) {
      finalData.push({serviceName: tmpObj.selectedTech + ',' + serviceName, rawDuration: tmpObj.rawDuration + rawDuration, selectedTech})
    }else {
      tmpObj = {
          serviceName,
          rawDuration,
          selectedTech
      }
      typeSelectedTech.add(selectedTech)

    }
}

addApptData("A", 20, "C");
addApptData("B", 30, "C");
addApptData("A", 20, "A");
addApptData("D", 40, "A");
console.log(finalData);
console.log(apptData);

First of all, I believe that you have solved the problem, my answer is only for communication.

I tried the rewriting method, you can get the raw data and the target data. Although it produces multiple global variables, I can't think of other ways.

So as a communication, I hope other people can have a better way.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.