Matthew Moran
Matthew Moran

Reputation: 1497

Transforming an object with a javascript class

I’m transforming data I receive from an API. The frontend requires some calculations to be displayed.

What is the proper way to handle the data transformation?


const dogData = {
  dog_name: "filo",
  born_time: 1530983852,
  coat_color: "brown"
};

class Dog {
  constructor(data) {
    //do I need to set this.dog to the data object, what's the benefit of doing so?
    this.dog = data;

    this.name = this.dog.dog_name;
    // vs
    this.name = data.dog_name;

    //Should I use setters and getters?
    this.color = this.dog.coat_color;
    // vs
    this._color = this.dog.coat_color;

    this.age = this.calculateAge();
  }

  calculateAge() {
    return Date.now().getTime() - this.dog.born_time;
  }

  //Is this a good case where I  should using getters to access the properties or would that be superfluous?
  //should I be setting the properties with setters in this case?
  get color() {
    return this._color;
  }
}

const dog = new Dog(dogData)

Upvotes: 1

Views: 166

Answers (3)

Peter Seliger
Peter Seliger

Reputation: 13432

Q:

Shall I nevertheless throw in a possible read only approach? – Peter Seliger

A:

It wouldn't hurt. I appreciate the different approaches. – Matthew Moran

... here we go ...

// module start ... e.g. file: "Dog.js"


// locally scoped helper function
function calculateAge(dateOfBirth) {
  return (Date.now() - dateOfBirth);
}

/*export default */class Dog {
  constructor(initialValue) {

    Object.defineProperties(this, {
      valueOf: { // just in order to hint what `initialValue` might still be good for.
        value: function () {
          return Object.assign({}, initialValue);
        }
      },
      name: {
        value: initialValue.dog_name,
        enumerable: true
      },
      color: {
        value: initialValue.coat_color,
        enumerable: true
      },
      age: {
        get() {
          return calculateAge(initialValue.born_time);
        },
        enumerable: true,
      }
    });
  }
}
// module end.


// test
const dogData = {
  dog_name: "filo",
  born_time: 1530983852,
  coat_color: "brown"
};

const dog = new Dog(dogData);

console.log('Object.keys(dog) : ', Object.keys(dog));
console.log('dog.valueOf() : ', dog.valueOf());

console.log('dog.age : ', dog.age);
console.log('dog.name : ', dog.name);
console.log('dog.color : ', dog.color);

console.log('(dog.age = 298146912) : ', (dog.age = 298146912) && dog.age);
console.log('(dog.name = "spot") : ', (dog.name = "spot") && dog.name);
console.log('(dog.color = "black") : ', (dog.color = "black") && dog.color);
.as-console-wrapper { max-height: 100%!important; top: 0; }

Upvotes: 0

Nishant Dixit
Nishant Dixit

Reputation: 5522

class Dog {
    constructor(data) {
        const {
            dog_name: name,
            born_time: age,
            coat_color: color
        } = data;
        Object.assign(this, {
            name,
            age,
            color
        });
    }
}

const dogData = {
    dog_name: "filo",
    born_time: 1530983852,
    coat_color: "brown"
};

const dog = new Dog(dogData);

console.log(dog.name);

Upvotes: 0

Blitz
Blitz

Reputation: 500

Your don't need to make a copy of data into your class.

You can assign the class fields directly (using object destructuring to be more readable).

const data = {
  dog_name: 'filo',
  born_time: 1530983852,
  coat_color: 'brown'
}

class Dog {
  // Directly assign values
  constructor({ dog_name, born_time, coat_color }) {
    this.name = dog_name
    this.bornAt = born_time
    this.color = coat_color
  }

  // Getter for computed properties
  get age() {
    return Date.now() - this.bornAt
  }
}

const dog = new Dog(data)

Getters are needed only for computed property (dynamic or formatted values).

Good exemple:

class Person {
  constructor({ firstname, lastname }) {
    this.firstname = firstname
    this.lastname = lastname
  }

  get fullname() {
    return `${this.firstname} ${this.lastname}`
  }
}

Upvotes: 2

Related Questions