Help understand why I get error "Cannot read property of undefined"

class Course {
    constructor(data){
        this.fwFactory = fwFactory.get(data.user, data.completed);
        this.title = data.title;
    }
}

const users = ['alex', 'paul', 'john', 'jessi'];
const completed = [true, false];

const CourseMethods = function() {
    
    const courses = {};
    let count = 0;

    const add = (data) => {
        courses[data.title] = new Course(data);
        count++;
    };

    const get = (title) => {
        return courses[title];
    };

    const getCount = () => {
        return count;
    };

    return {
        add: add,
        get: get,
        getCount: getCount
    };
};
//====================================================================================
class FlyWeight {
    constructor(user, completed){
        this.user = user;
        this.completed = completed;
    }
}

class fwFactory {
   
    constructor() {
        this.fw_comm = {};
    }

    static get(user, completed) {
        if (!this.fw_comm[user + completed]) {
            fw_comm[user + completed] = new FlyWeight(user, completed);
        }

        return fw_comm[user + completed];
    }

    static getCount() {
        let count = 0;
        for (let c in fw_comm) count ++;
        return count;
    }
}
//====================================================================================

const initMem = process.memoryUsage().heapUsed;
courses = new CourseMethods();
const numCourses = 1000000;

for (let i = 0; i < numCourses; i++) {
    courses.add({
        title: i + '.course',
        user: users[Math.floor(Math.random() * 4)],
        completed: completed[Math.floor(Math.random() * 2)]
    });
}

const finalMem = process.memoryUsage().heapUsed;
const usedMem = ((finalMem - initMem) / 1000000).toFixed(2);
console.log(usedMem  + ' Mb');

fwcourses = new fwFactory();
for (let i = 0; i < numCourses; i++) {
    fwcourses.add({
        title: i + '.course',
        user: users[Math.floor(Math.random() * 4)],
        completed: completed[Math.floor(Math.random() * 2)]
    });
}

I get in line if (!this.fw_comm[user + completed]) { error “Cannot read property of undefined” please help me understand what this mean and why I get it. Thanks

Hi @william1, you defined the get() method as static, so this refers to the class itself rather than to a class instance you created with new. And calling static methods doesn’t involve the constructor in any way, so fwFactory.fw_comm is indeed undefined.

So you’d either have to define those methods as regular ones and create an instance first…

class FwFactory {   
  constructor () {
    this.fwComm = {};
  }
  
  get (user, completed) {
    if (!this.fwComm[user + completed]) {
      this.fwComm[user + completed] = new FlyWeight(user, completed);
    }
    
    return this.fwComm[user + completed];
  }
  
  getCount () {
    return Object.keys(this.fwComm).length
  }
}

const fwFactory = new FwFactory()
fwFactory.get(...)

… or simply use an object literal instead:

const fwFactory = {
  fwComm: {},
  
  get (user, completed) {
    if (!this.fwComm[user + completed]) {
      this.fwComm[user + completed] = new FlyWeight(user, completed);
    }
    
    return this.fwComm[user + completed];
  },
  
  getCount () {
    return Object.keys(this.fwComm).length
  }
}
1 Like

Thanks I tried now like this

class Course {
    constructor(data){
        this.fwFactory = fwFactory.get(data.user, data.completed);
        this.title = data.title;
    }
}

const users = ['alex', 'paul', 'john', 'jessi'];
const completed = [true, false];

const CourseMethods = function() {
    
    const courses = {};
    let count = 0;

    const add = (data) => {
        courses[data.title] = new Course(data);
        count++;
    };

    const get = (title) => {
        return courses[title];
    };

    const getCount = () => {
        return count;
    };

    return {
        add: add,
        get: get,
        getCount: getCount
    };
};
//====================================================================================
class FlyWeight {
    constructor(user, completed){
        this.user = user;
        this.completed = completed;
    }
}

class fwFactory {
   
    constructor() {
        this.fw_comm = {};
    }

    get(user, completed) {
        if (!this.fw_comm[user + completed]) {
            fw_comm[user + completed] = new FlyWeight(user, completed);
        }

        return fw_comm[user + completed];
    }

    getCount() {
        //let count = 0;
        //for (let c in fw_comm) count ++;
        return Object.keys(this.fw_comm).length;
    }
}
//====================================================================================

courses = new CourseMethods();

// for (let i = 0; i < numCourses; i++) {
//     courses.add({
//         title: i + '.course',
//         user: users[Math.floor(Math.random() * 4)],
//         completed: completed[Math.floor(Math.random() * 2)]
//     });
// }
const numCourses = 1000000;
const initMem = process.memoryUsage().heapUsed;
const finalMem = process.memoryUsage().heapUsed;
const usedMem = ((finalMem - initMem) / 1000000).toFixed(2);
console.log(usedMem  + ' Mb');

fwcourses = new fwFactory();
for (let i = 0; i < numCourses; i++) {
    courses.add({
        title: i + '.course',
        user: users[Math.floor(Math.random() * 4)],
        completed: completed[Math.floor(Math.random() * 2)]
    });
}

but now in get line error fwFactory.get is not a function. any advise ? I dont want to use object literal.

That is because now you have to create a class instance first, on which you can then call .get() (see my above snippet again). BTW by convention class names are written PascalCase (starting with a capital letter) which helps avoiding such confusion.

Any particular reason? ^^

1 Like

I just want to learn all methods. I got it now worked many thanks here is the complete code.

class Course {
    constructor(data){
        const fwFactory = new FWFactory();
        fwFactory.get(data.user, data.completed);
        this.title = data.title;
    }
}

const users = ['alex', 'paul', 'john', 'jessi'];
const completed = [true, false];

const CourseMethods = function() {
    
    const courses = {};
    let count = 0;

    const add = (data) => {
        courses[data.title] = new Course(data);
        count++;
    };

    const get = (title) => {
        return courses[title];
    };

    const getCount = () => {
        return count;
    };

    return {
        add: add,
        get: get,
        getCount: getCount
    };
};
//====================================================================================
class FlyWeight {
    constructor(user, completed){
        this.user = user;
        this.completed = completed;
    }
}

class FWFactory {
   
    constructor() {
        this.fw_comm = {};
    }

    get(user, completed) {
        if (!this.fw_comm[user + completed]) {
            this.fw_comm[user + completed] = new FlyWeight(user, completed);
        }

        return this.fw_comm[user + completed];
    }

    getCount() {
        //let count = 0;
        //for (let c in fw_comm) count ++;
        return Object.keys(this.fw_comm).length;
    }
}
//====================================================================================

courses = new CourseMethods();

// for (let i = 0; i < numCourses; i++) {
//     courses.add({
//         title: i + '.course',
//         user: users[Math.floor(Math.random() * 4)],
//         completed: completed[Math.floor(Math.random() * 2)]
//     });
// }
const numCourses = 1000000;
const initMem = process.memoryUsage().heapUsed;

for (let i = 0; i < numCourses; i++) {
    courses.add({
        title: i + '.course',
        user: users[Math.floor(Math.random() * 4)],
        completed: completed[Math.floor(Math.random() * 2)]
    });
}

const finalMem = process.memoryUsage().heapUsed;
const usedMem = ((finalMem - initMem) / 1000000).toFixed(2);
console.log(usedMem  + ' Mb');

Many Thanks

I got it getCount() :slight_smile: many thanks my friend :bouquet:

1 Like

No worries! :-) One thing to note though, for each Course instance you’re now creating a new FWFactory, each of which briefly holding a single fw_conn entry before immediately getting discarded again after the .get() call. If you want to maintain (und reuse) a number of FlyWeight objects you’ll have to create a single instance outside the Course constructor, i.e.

const fwFactory = new FWFactory()

class Course {
  constructor (data) {
    this.flyWeight = fwFactory.get(data.user, data.completed)
    this.title = data.title
  }
}

// Then somewhere else...
const count = fwFactory.getCount()
1 Like

I think also this faster and uses less memory which is the point of this code.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.