0

I have a custom Javascript class Workout with a custom method to copy itself.

When I use the copyWorkout method as part of a loop through an array of Workouts inside a getCalArray function, I can get the function to pass tests, but when I use that function inside another function, I get a TypeError - copyWorkout is not a function;

Any ideas? It seems like Javascript interpreter can no longer find the class/type, but I have no idea how to fix this.

let Workout = class {
    constructor(workoutNumber, weekNum = Math.ceil(workoutNumber/7),
                title = 'Rest Day', description = '', workoutDate = null) {
        this.workoutNum = workoutNumber;
        this.weekNum = weekNum;
        this.title = title;
        this.description = description;
        this.workoutDate = workoutDate;


    }

    addDate(inputDate) {
        this.workoutDate = inputDate;
    }

    toString() {
        return `Workout Num: ${this.workoutNum}, Week Num: ${this.weekNum}, 
        title: ${this.title}, description: ${this.description}, Workout Date: ${this.workoutDate},`
    }

    copyWorkout = () =>  {
        return new Workout(this.workoutNum, this.weekNum, this.title, this.description, this.workoutDate);
    }
}

function getDateDaysFrom(numDays, inputDate) {

    let outputDate = new Date(inputDate.getTime());

    outputDate.setDate(outputDate.getDate() + numDays);

    return outputDate;

}

const dateFromString = (inputDate) => {

    const dateArr = inputDate.split('-');

    const m = dateArr[0];
    const d = dateArr[1];
    const y = dateArr[2];

    return new Date(y, m-1, d, 0, 0, 0, 0);
};

const getStartDate = (numDaysOfWorkoutSchedule, raceDate) => {
    let startDate = getDateDaysFrom(-numDaysOfWorkoutSchedule, dateFromString(raceDate));

    while (startDate.getDay() !== 0) {
        startDate = getDateDaysFrom(-1, startDate);
    }
    return startDate;
};

const getCalArray = (startDateStr, workoutSchArr) => {
    let i;
    let daysAvailable;
    let currentWeek;
    let lastWeekNum = 0;
    let calendarArray = [];
    let calWeekArray = [];

    let startDate = getStartDate(0, startDateStr);

    for (i=0; i<workoutSchArr.length; i++) {

        currentWeek = workoutSchArr[i].weekNum;

        if (currentWeek !== lastWeekNum) {
            //for each day if true, then available.  if false, then booked
            daysAvailable = [true, true, true, true, true, true, true];
            if (lastWeekNum > 0) {
                calendarArray.push(calWeekArray) ;
                calWeekArray = [];
            }
        }
        let newDate;
        //find first available day and set date based on day and weeknum
        if (daysAvailable[0]) {
            newDate = getDateDaysFrom((currentWeek-1)*7, startDate)
            daysAvailable[0] = false;
        } else if (daysAvailable[1]) {
            newDate = getDateDaysFrom((currentWeek-1)*7+1, startDate)
            daysAvailable[1] = false;
        } else if (daysAvailable[2]) {
            newDate = getDateDaysFrom((currentWeek-1)*7+2, startDate)
            daysAvailable[2] = false;
        } else if (daysAvailable[3]) {
            newDate = getDateDaysFrom((currentWeek-1)*7+3, startDate)
            daysAvailable[3] = false;
        } else if (daysAvailable[4]) {
            newDate = getDateDaysFrom((currentWeek-1)*7+4, startDate)
            daysAvailable[4] = false;
        } else if (daysAvailable[5]) {
            newDate = getDateDaysFrom((currentWeek-1)*7+5, startDate)
            daysAvailable[5] = false;
        } else if (daysAvailable[6]) {
            newDate = getDateDaysFrom((currentWeek-1)*7+6, startDate)
            daysAvailable[6] = false;
        }

        let newWorkout = workoutSchArr[i].copyWorkout();
        newWorkout.addDate(newDate);

        calWeekArray.push(newWorkout);
        lastWeekNum = currentWeek;
    }
    calendarArray.push(calWeekArray);

    return calendarArray;

};

let printWorkoutSchedule = (workoutSchedule) => {
    let outputString = "";
    let i;
    for (i=0; i<workoutSchedule.length; i++) {
        const workout = workoutSchedule[i];
        const workoutString = `Workout ${workout.workoutNum} - 
        Week ${workout.weekNum} - ${workout.title} ${workout.description}`;
        outputString += workoutString + '\n';
    }

    return outputString;
};

let inputArray = [new Workout(1, 1, 'SWIM:',
        '600yds 4 x 50yds, 4 x 100yds'), new Workout(2, 1, 'BIKE:',
        '45 minutes'), new Workout(3, 1, 'RUN:',
        '15 minutes'), new Workout(4, 2, 'SWIM:',
        '700yds 6 x 50yds, 4 x 100yds'), new Workout(5, 2, 'BIKE:',
        '45 minutes'), new Workout(6, 2, 'RUN:',
        '20 minutes'), ];
let startDate = '09-01-2020';

let calArrayExample = getCalArray(startDate, inputArray)

console.log(printWorkoutSchedule(calArrayExample));
  • It would help a lot if you showed your code, and even better if you can reproduce the problem with a demo in your question (use the '<>' button in the toolbar) – blex Dec 10 '20 at 17:30
  • Can you add the `getCalArray` function code please? – Andres Gardiol Dec 10 '20 at 18:33
  • 1
    Your `getCalArray` method parameters seems to be interchanged. On the last but first line change it to `let calArrayExample = getCalArray(startDate, inputArray)` – Parikshith Kedilaya M Dec 10 '20 at 20:42

1 Answers1

0

So I figured out a work around where I wasn't using a class method to copy and instead did a copy using this method - How to clone a javascript ES6 class instance

So instead of copyWorkout()... I am now using Object.assign(Object.create(Object.getPrototypeOf(WorkoutArr[i])), WorkoutArr[i]) to create a copied instance of the Workout.

Seems to resolve all my previous problems, but I am still curious about how to get more type stability without moving to Typescript.