8

I am having a lot of trouble writing an object oriented Cat class in Node.js. How can I write a Cat.js class and use it in the following way:

// following 10 lines of code is in another file "app.js" that is outside 
// the folder "model"
var Cat = require('./model/Cat.js');

var cat1 = new Cat(12, 'Tom');
cat1.setAge(100);
console.log(cat1.getAge()); // prints out 100 to console

var cat2 = new Cat(100, 'Jerry');
console.log(cat1.equals(cat2)); // prints out false

var sameAsCat1 = new Cat(100, 'Tom');
console.log(cat1.equals(sameAsCat1)); // prints out True

How would you fix the following Cat.js class I have written:

 var Cat = function() {
    this.fields = {
        age: null,
        name: null
    };

    this.fill = function (newFields) {
        for(var field in this.fields) {
            if(this.fields[field] !== 'undefined') {
                this.fields[field] = newFields[field];
            }
        }
    };

    this.getAge = function() {
        return this.fields['age'];
    };

    this.getName = function() {
        return this.fields['name'];
    };

    this.setAge = function(newAge) {
        this.fields['age'] = newAge;
    };

    this.equals = function(otherCat) {
        if (this.fields['age'] === otherCat.getAge() && 
            this.fields['name'] === otherCat.getName())  {
            return true;
        } else {
            return false;
        }
    };
};

module.exports = function(newFields) {
    var instance = new Cat();
    instance.fill(newFields);
    return instance;
};
3
  • Whether this is the only issue, I cannot say, but you want to test typeof() !== 'undefined' in your fill function. And because you assign them null values, that wouldn't work out anyway, because you'll get 'object' back on typeof. If you just assign them as undefined and test for that via typeof(), it would otherwise appear it should behave as you expect. Commented Mar 25, 2014 at 4:18
  • 1
    What exactly is the problem you need help with? Commented Mar 25, 2014 at 5:00
  • You might want to have a look at TidBits OoJs. It's reliable and gives you about all OO features you might dream of except for multiple inheritance in a simple and natural syntax. Commented Apr 2, 2014 at 12:09

4 Answers 4

13

If I were to design an object like this, then I would have done like this

function Cat(age, name) {       // Accept name and age in the constructor
    this.name = name || null;
    this.age  = age  || null;
}

Cat.prototype.getAge = function() {
    return this.age;
}

Cat.prototype.setAge = function(age) {
    this.age = age;
}

Cat.prototype.getName = function() {
    return this.name;
}

Cat.prototype.setName = function(name) {
    this.name = name;
}

Cat.prototype.equals = function(otherCat) {
    return otherCat.getName() == this.getName()
        && otherCat.getAge() == this.getAge();
}

Cat.prototype.fill = function(newFields) {
    for (var field in newFields) {
        if (this.hasOwnProperty(field) && newFields.hasOwnProperty(field)) {
            if (this[field] !== 'undefined') {
                this[field] = newFields[field];
            }
        }
    }
};

module.exports = Cat;     // Export the Cat function as it is

And then it can be used like this

var Cat = require("./Cat.js");

var cat1 = new Cat(12, 'Tom');
cat1.setAge(100);
console.log(cat1.getAge());                 // 100

var cat2 = new Cat(100, 'Jerry');
console.log(cat1.equals(cat2));             // false

var sameAsCat1 = new Cat(100, 'Tom');
console.log(cat1.equals(sameAsCat1));       // true

var sameAsCat2 = new Cat();
console.log(cat2.equals(sameAsCat2));       // false

sameAsCat2.fill({name: "Jerry", age: 100});
console.log(cat2.equals(sameAsCat2));       // true
Sign up to request clarification or add additional context in comments.

2 Comments

@Chingy I am assuming yours. Try with == instead of === :)
or now better in ES6.
3

I would use a class :

class Cat {
    fields = {
        age: null,
        name: null
    };

    fill(newFields) {
        for(var field in this.fields) {
            if(this.fields[field] !== 'undefined') {
                this.fields[field] = newFields[field];
            }
        }
    }

    getAge() {
        return this.fields.age;
    }

    setAge(newAge) {
        this.fields.age = newAge;
    }
}

exports.Cat = Cat;

3 Comments

I came to give the same answer and saw this -4 answer, omg. What's wrong with it?
@Asqan maybe because the question asks for JS, not TypeScript. And you can't 'use' TypeScript in the browser, it needs to be compiled to JS first.
I've removed TypeScript from the answer as really modern JavaScript has the feature (classes) I'm recommending.
0

This code is working fine Person.js code here

  exports.person=function(age,name)
    {
        age=age;
        name=name;
        this.setAge=function(agedata)
        {
           age=agedata;
        }
        this.getAge=function()
        {
            return age;
        }
        this.setName=function(name)
        {
            name=name;
        }
        this.getName=function()
        {
            return name;
        }

};

call object code:

var test=require('./route/person.js');
var person=test.person;
var data=new person(12,'murugan');
data.setAge(13);
console.log(data.getAge());
data.setName('murugan');
console.log(data.getName());

Comments

0

There is error loop hole in answers by @thefourtheye, I will describe those below

Object modelling rules

  • Create empty new object

  • Create Filled Object

  • Only Initial object should be set by machine/code

  • After Initial object assignment Any changes in your object should happen by user interaction only.

  • After Initial object assignment Any changes in object by code without user intention is going to add some bugs

Problem Use case :

Eg - So when you create filled object , at that time if any property(somedate) is not having any value then due to below code the default value gets assigned to it(somedate) , which is against object modelling rules.

  • Bug

  • Constructor function is given Dual responsibility to create new & filled object which he mixes up while creating filled object , And its going to make mistakes.

  • Means there is some buggy code in your app that is going to set values by it self without users intention

    function Cat(age, name, somedate ) { // Accept name and age in the constructor this.name = name || null; this.age = age || null; this.somedate = somedate || new Date(); //there will be lots of usecases like this }

So to solve this Problem i use below JavaScript data model.

So it allows user to create filled object Or new object intentionally only when need any one of them and not messing with each other

class Cat {
    constructor(){
        this.name = null;
        this.age = null;
    }

    initModel (data) {
        this.name = data.name;
        this.age = data.age
    }

    getAge () { return this.age;}

    setAge (age) { this.age = age; }

    getName () {this.name;}

    setName (name) {this.name = name;}

    equals (otherCat) {
        return otherCat.getName() == this.getName()
            && otherCat.getAge() == this.getAge();
    }

    fill (newFields) {
        for (let field in newFields) {
            if (this.hasOwnProperty(field) && newFields.hasOwnProperty(field)) {
                if (this[field] !== 'undefined') {
                    this[field] = newFields[field];
                }
            }
        }
    };
    
}


let cat1 = new Cat();
cat1.initModel({age : 12,name :'Tom'})
cat1.setAge(100);
console.log(cat1.getAge());                 // 100

let cat2 = new Cat();
cat2.initModel({age : 100,name : 'Jerry'})
console.log(cat1.equals(cat2));             // false

let sameAsCat1 = new Cat({age : 100,name : 'Tom'});
sameAsCat1.initModel({age : 100,name : 'Tom'})
console.log(cat1.equals(sameAsCat1));       // true

let sameAsCat2 = new Cat();
console.log(cat2.equals(sameAsCat2));       // false

sameAsCat2.fill({name: "Jerry", age: 100});
console.log(cat2.equals(sameAsCat2)); 

  • Note :
  • Constructor is only used For creating new Object
  • InitModel is only used For creating filled Object

1 Comment

How to use that class on another js file? I've tried import { Cat } from "./app/models/cat.model.js" but I got error Cannot use import statement outside a module

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.