0

I had made an abstract class:

class Model {
  attributes = [];

  constructor(data) {
    this._importAttributes(data);
  }

  _importAttributes(data) {
    this.attributes.forEach((attr) => {
      this[key] = data[attr];
    });
  }
}

and then extended from that abstract class:

import Model from './model';

class Promotion extends Model {
  attributes = ['id', 'shop_name', 'title', 'description', 'end_time'];

  // No need to state this constructor, just want to state out the problem clearly
  constructor(data) {
    super(data); // <-- Problem occured in here,
    // this.attributes is empty array inside parent constructor
  }
}

so that I could use the class like this way:

let promotion = new Promotion({'id': 1, 'shop_name': 'Sample'....});

------ WHAT I WOULD LIKE TO ACHEIVE ------

I would like to use the _importAttributes() function inside constructor() of all extends child class. Simply just state the attributes of the child class and start to use easily.

------ PROBLEM ENCOUNTERED ------

When I call constructor() in the Promotion class,
it cannot get attributes of the Promotion class.

Appreciate for any kindly help.

Wing Choy
  • 900
  • 10
  • 25

2 Answers2

1

There's quite a few things wrong here.

This is a syntax error:

class Model {
  attributes = [];
  // ...
}

You can't just define properties on a class. You need to define attributes in the constructor with something like this.attributes = ['attribute']. Since the base class constructor calls _importAttributes you can't call super() and then add the attributes in the child class because you need to call super() first.

You also have this[key] = data[attr]; but key isn't defined. I assume that should be attr.

I think a good way to do this would be to pass the attributes as a parameter to super with a default value of []. Then the parent class can add this.attributes to the instance before calling _importAttributes.

Something like:

class Model {
    constructor(data, attributes=[]) { // accepts attributes
        this.attributes = attributes   // adds them to instance
        this._importAttributes(data);  // now you can use them
    }
  
    _importAttributes(data) {
      this.attributes.forEach((attr) => {
        this[attr] = data[attr];
      });
    }
  }
  
  class Promotion extends Model {
    constructor(data) {
      super(data, ['id', 'shop_name', 'title', 'description', 'end_time']); // pass attributes
    }
  }

let promotion = new Promotion({'id': 1, 'shop_name': 'Sample'})
console.log(promotion)
Mark
  • 90,562
  • 7
  • 108
  • 148
0

As of 2018, the ES6 class syntax not support define class property yet. See this link for more details. The only way to achieve what you want is to define class property in constructor function (See answer from Mark Meyer)

Also, notice that the class keyword in ES6 is just syntactic sugar to create constructor similar to other OOP languages. It's still in its early form so we need to wait for a few versions for it to fully support other features. There is a proposal in ES7 that allow defining properties within class construct

Dat Pham
  • 1,765
  • 15
  • 13