Home > Mobile >  Add properties to a constructor class after loading
Add properties to a constructor class after loading

Time:10-17

I have a class Model that gets extended by many other definition models, in this example we'll use HorseModel. These are being used in Vue3, in which webpack is bundling them up as part of the build.

class HorseModel extends Model {
    constructor(record, config = {}){
        super(record, config);
    }

    static getProperties = () => {
        return {
            'rider': {type: RiderModel, nullable: true}
        }
    }
}

class RiderModel extends Model {
    constructor(record, config = {}){
        super(record, config);
    }

    static getProperties = () => {
        return {
            'horse': {type: HorseModel, nullable: true}
        }
    }
}

Originally, I had a properties object as a static property on the definition model class, however these objects may reference other definition models, which in turn may circular reference back to the original definition model, which upsets webpack. To overcome this issue, I wrapped the properties object in a function. This works.

My concern now is that because the properties object isn't something I can just access on the base constructor, I see two not-ideal options:

  1. Call the getProperties function each time I need a value (what I'm doing currently)
  2. Add the properties when constructing each instance of the definition models, which replicates the otherwise static values in memory for each instance.

I also tried defining the properties object outside of the class, then having getProperties return a reference to that object, so at least all instances would point to the same object. This revealed an immediate issue with self-referencing definition models, Cannot access 'HorseModel' before initialization

Is there some way to add these properties as a static property at some point later, maybe on DOM ready, to avoid the webpack circular reference issue and be able to access these in one place in memory?


Circular ref problem example:

class HorseModel extends Model {
    constructor(record, config = {}){
        super(record, config);
    }

    static properties = {
        'rider': {type: RiderModel, nullable: true}
    }
}

class RiderModel extends Model {
    constructor(record, config = {}){
        super(record, config);
    }

    static properties = {
        'horse': {type: HorseModel, nullable: true}
    }
}

The type property of whichever one is bundled second will be undefined.

CodePudding user response:

For circular references and references to classes that have not yet been initialised, creating the object lazily (on access, not with the class definition) is unavoidable. I would recommend a getter for this, not a method.

To make it more efficient and not create a new object on every access, the getter can be memoised. I often do that by making the getter overwrite itself with a normal data property:

class HorseModel extends Model {
    static get properties() {
        const value = {'rider': {type: RiderModel, nullable: true}};
        Object.defineProperty(this, 'properties', {value});
        return value;
    }
}

class RiderModel extends Model {
    static get properties() {
        const value = {'horse': {type: HorseModel, nullable: true}};
        Object.defineProperty(this, 'properties', {value});
        return value;
    }
}

CodePudding user response:

This does not work

Upon not being dumb further testing it becomes obvious that the circular reference issue does in fact persist with this implementation. Leaving this up for posterity.


While this doesn't quite go as far as adding the property after load, it does overcome circular- and self-referencing issues while pointing back to a singular instance of the properties object in question:

class HorseModel extends Model {
    constructor(record, config = {}){
        super(record, config);
    }

    static getProperties = () => {
        return _properties;
    }
}

const _properties = {
    'name': {type: String, nullable: true, ...}
    ...
}

Declare the properties object after the class, as the class is not accessing it until the getProperties function is actually called.

  • Related