1

Here is a little background.

So I have my parent class. Constructor receives two objects: the first one is the class where the instance of the parent object was created (using others classes which are inheriting parent class). The second object are just some parameters

parent.js

class ParentClass {
    constructor(nativeObject, params) {
        this.nativeObject = nativeObject;
        this.param1 = params.param1;
        this.param2 = params.param2;
    }
    // some logic here
}
module.exports = { ParentClass };

child.js

class ChildClass extends ParentClass {
    // some logic here
}
module.exports = { ChildClass };

I'm using the child class in the other class methods for creating it. I can have multiple files like below:

usingclasses.js

let { ChildClass } = require('path/to/my/child/class');

let opts = {
    param1: 'idkSomeString';
    param2: 42;
}


class MyCoolClass {
    createChild() {
        return new ChildClass(this, opts);
    }
}
module.exports = { MyCoolClass };

anotherclasses.js

let { ChildClass } = require('path/to/my/child/class');

let opts = {
    param1: 'thatAstringToo';
    param2: 123;
}

class AnotherCoolClass{
    alsoCreatesChild() {
        return new ChildClass(this, opts);
    }
}
module.exports = { AnotherCoolClass};

I can create multiple instances of the ChildClass in a different methods within one class:

thirdexample.js

let { ChildClass } = require('path/to/my/child/class');

let opts1 = {
    param1: 'aStringAgain';
    param2: 27;
}

let opts2 = {
    param1: 'ABC';
    param2: 33;
}

class ClassAgain{
    firstMethod() {
        return new ChildClass(this, opts1);
    }

    secondMethod() {
        return new ChildClass(this, opts2);
    }
}
module.exports = { ClassAgain };

The reason why I'm passing .this because I'm working with it in ParentClass

e.g for logging console.log(`I know this was created in ${this.nativeObject .constructor.name}`);

What I'm looking for is the way to get rid of passing .this every time I'm creating a new instance of the ChildClass

Reason behind this is that in one file (class) I can create up to 10+ instances of the ChildClass.

In the previous question I already got an answer which helped me to make the code more structured and more easy to maintain:

Instead of:

createChild() {
        return new ChildClass(this, param1, param2, param3, paramN);
    }

I'm doing:

createChild() {
        return new ChildClass(this, paramObj);
}

So now I can store all my objects with parameters at the top of the file (of even separate file) and easily find and change it if needed.
...

Now I'm trying to find a way to get rid of .this every time I'm creating ChildClass

Is there any other way how ParentClass can know where does this ChildClass instances "lives"?

I'm trying to figure out can I do something using .apply or .call but seems like this is not a droids I'm looking for

UPDATE: Since I have zero progress on this and I even got a comment that most likely this is not possible let's assume for now that I need a name of the class that is creating instance of the ChildClass only for logging.

How can I retrieve the name of the class without passing it every time when creating a ChildClass?

let opts = {
    className: 'MyCoolClass'
    param1: 'idkSomeString';
    param2: 42;
}


class MyCoolClass {
    createChild() {
        return new ChildClass(opts);
    }
}
module.exports = { MyCoolClass };

The problem is that I will have to set className: 'MyCoolClass' in each version of opts again and again and again... Just repeat the same for 10-15 times

anotheruser
  • 582
  • 1
  • 7
  • 23
  • I researched on `.call` and looks like it's not what I'm looking for. Because when using `.call` I'm specifying which context I want to assign. And in my case I don't know it since class can be created in a tons of different places... – anotheruser Dec 19 '19 at 14:37
  • No, this is not possible. If it is just a matter of logging to the console, you can dump the stack trace with `console.trace()`. There is also the non-standard [caller](https://stackoverflow.com/q/280389/5459839) property. But even those solutions will not exactly give you the name of the constructor. So, you'll have to pass `this`. It would be nice to know why you need to know this piece of information. Maybe then we can propose a different set up. – trincot Dec 19 '19 at 15:09
  • Also, realise that such a `createChild` method can be called with a different `this`, like `myCoolInstance.createChild.call({ a: "b"})`, so then your setup will see `Object` as the constructor. – trincot Dec 19 '19 at 15:12
  • 'Also, realize that such' so you are saying that if I will do `.call` on a `createChild` method I will get a wrong "parent" class? Let's just assume it will never happen. For first comment please see updated question – anotheruser Dec 20 '19 at 07:25
  • 1
    Well for the last part of your question if your classname is same for the all versions or you save some non-changing properties you can define a default options and derive the versions with the help of Object.assingn : `const derivedOpt = Object.assign({},defaultOpts,newOpts)` – Eldar Dec 20 '19 at 07:48

1 Answers1

0

You can just instantiate your classes using Reflect.construct.

class ParentClass {
  constructor (nat, x) {
    this.nat = nat
    this.x = x
  }
  log () {
    console.log('from ', this.nat.constructor.name, this.x)
  }
}
class ChildClass extends ParentClass{}

class ClassAgain{
  firstMethod () {
    return this.makeInstance({ a: 1 })
  }

  secondMethod () {
    return this.makeInstance({ b: 2 })
  }

  makeInstance (params) {
    return Reflect.construct(ChildClass, [this, params])
  }
}
const ca = new ClassAgain()
ca.firstMethod().log()
ca.secondMethod().log()
grodzi
  • 5,633
  • 1
  • 15
  • 15
  • It looks like it behaves the same way as simply returning the `new` class. How can I benefit from this? – anotheruser Dec 20 '19 at 14:18
  • I assumed your problem was to consider Child1 and Child2. Thus you want to avoid repeating giving this as argument. Idea was to pass Child1 or Child2 as argument to makeInstance so you don't have to repeat giving this as argument. it may be a mistake on my part if your sole goal is to avoid giving this nor any reference. If you confirm this I will just remove that post – grodzi Dec 20 '19 at 17:22