Create object of class within a class but not using the name - javascript

I am sorry if the heading is misleading, I can't think of a better heading.
so I have two classes like this :
class ClassA{
getObject(){
return new this(with some parameters)
}
}
class ClassB extends classA{
}
let a = new ClassB();
a.getObject();
I know I can always return new ClassB() with some parameters. But ClassA is extended by some hundred classes and it will be a lot of change in every class.
So Is there a way to return object of self class in getObject method of ClassA?

You can use polymorphic this to return an instance of the same type as the current class:
class ClassA {
getObject(): this {
// not really type safe, not really recomnded
return new (this as any).constructor()
}
}
class ClassB extends ClassA {
}
let a = new ClassB();
let b = a.getObject(); // ClassB
console.log(a.getObject() instanceof ClassB); // true
You can also infer the type of this using a type parameter and use that as the return type:
class ClassA {
getObject<T>(this:T) : T {
// not really type safe
return new (this as any).constructor()
}
}
class ClassB extends ClassA {
}
let a = new ClassB();
let b = a.getObject(); // ClassB
console.log(a.getObject() instanceof ClassB); // true

Related

Is there a way to reference "the current class" from a Javascript class method

I'm wondering if there's a way to reference the "current class" rather than a class by name, from within a Javascript class.
For example:
class MyBase{
static makeNew(id){
const newInstance = new --currentClass--;// magic happens here
newInstance.id = id;
return newInstance;
}
}
class A extends MyBase{}
class B extends MyBase{}
const newA = A.makeNew(1);
const newB = B.makeNew(379);
Is there a way for me to write MyBase::makeNew in such a way that when it's called from the A class, it returns a new instance of A, but when called from the B class, it returns a new instance of B?
Since the call signatures are like:
A.makeNew(1);
B.makeNew(379);
That might look familiar - you can use this to reference the object it's being called on.
class MyBase{
static makeNew(id){
const newInstance = new this();
newInstance.id = id;
return newInstance;
}
}
class A extends MyBase{}
class B extends MyBase{}
const newA = A.makeNew(1);
const newB = B.makeNew(379);
console.log(newA instanceof A);
console.log(newB instanceof B);

Multiple classes that have a different name but extends the same class

I have for example this class:
abstract class MyClass {
abstract myProp: number;
constructor() {
// Some code
}
}
So I want to create multiple classes that extends this class. But I don't want to repeat it multiple times as I will have a lot of classes. So the purpose is that each class has a different name and myProp.
For example:
class FirstClass extends MyClass {
myProp = 1;
constructor() {
super();
// Some code
}
}
class SecondClass extends MyClass {
myProp = 2;
constructor() {
super();
// Some code
}
}
So I want to generate these classes (with for example a function) but the problem is that I will have to use the new keyword.
So the usage for each of these classes should be like this:
const myConst = new FirstClass();
const myConst2 = new SecondClass();
I hope this makes some sense. I just don't want to repeat every class because it has a different name and myProp.
You can create classes through a function that returns an anonymous class.
const createClass = ( prop: number ) => {
return class extends MyClass {
myProp: number;
constructor () {
super();
this.myProp = prop;
}
}
}
const FirstClass = createClass(1);
const x = new FirstClass();
console.log(x.myProp);
Or check out the answers to these questions for ideas:
ES6 Dynamic class names
Create object from class name in JavasScript ECMAScript 6
If I understand your problem correctly, you could just pass the variable that's different as an argument in the constructor.
class MyClass {
myProp: number;
constructor(myProp: number) {
this.myProp = myProp
// Some code
}
}
And then create the class instances you want.
const myConst = new MyClass(1);
const myConst2 = new MyClass(2);
Personally, I would only extend a class if I want to add some methods or properties that aren't shared. Since myProp exists in both classes, it's probably better to just pass the value to the constructor.

Javascript ES2015 : Instanciate a class and use variables from class

I have a class B which implements another class A.
In the class A I need to use variables defined in class B
class classA {
methodA() {
console.log(parentClass.variableToRetrieve);
}
}
class classB {
constructor() {
this.variableToRetrieve = 1;
this.A = new classA();
}
}
var B = new classB();
B.A.methodA();
Whats should I use in classA.methodA ans see 1 in the console ?
Edit
I already thougth to pass the B object in the classA constructor, or pass values, but as I can have hundreds variables and (potentially) millions classA, it will fuck the server quickly
You should extend classB with classA
class classA {
methodA() {
console.log('parentClass.variableToRetrieve');
}
}
class classB extends classA {
constructor() {
super()
this.variableToRetrieve = 1;
}
method() {
this.A = new classA();
}
}
var B = new classB();
B.methodA();
Updated:
I think binding the classB will solve will problem.
class classA {
methodA() {
console.log(this.variableToRetrieve);
}
}
class classB {
constructor() {
this.variableToRetrieve = 4;
}
}
var B = new classB();
var A = new classA();
A.methodA.bind(B)();
Your class A must extend class class B to do that

Ecmascript 6 Class: access constructor created method of super class

I'm creating methods inside a constructor, to work with private values - this seems to be the suggested pattern to create private properties and limit the access to them.
Now I inherit from that class and within the constructor of the derived class I create another method, trying to access that. Unfortunately I get an exception TypeError: ... is not a function.
What to do? I can use the constructor as exactly that and just create a new object, but that would not be related to its classes and copying all the properties of the class and the super class etc. seems quite annoying and not like the right way. So again, what to do?
Here is an example:
class ClassA {
constructor() {
this.getValue = () => "private value";
}
}
class ClassB extends ClassA {
constructor() {
super();
this.getValue = () => `${super.getValue()}, second private value`;
}
}
const a = new ClassA();
const b = new ClassB();
console.log(`a.getValue = ${a.getValue()}`);
console.log(`b.getValue = ${b.getValue()}`);
Fiddle Check the console. The outcome I'd expect is "private value, second private value".
If someone can give me a hint, or a not super shitty workaround, I'd appreciate that.
Thanks, fea
super refers to the classes prototype. As your methods are not prototype methods but instance methods, it will unfortunately not work. However you could store the original function reference in a variable:
const orig = this.getValue.bind(this);
this.getValue = () => `${orig()}, second private value`;
However i personally rather like the _ pattern:
class ClassA {
constructor() {
this._private = "test";
}
getValue(){ return this._private; }
}
class ClassB extends ClassA {
constructor() {
super();
}
getValue(){
return `${super.getValue()}, second private value`;
}
}

js call base class constructor

Is it possible to call a baseclass constructor from a class?
class BaseCls {
}
class Cls extend BaseCls {
constructor(options){
super(options)
}
}
var instance = new Cls();
Now I want an instance of the baseclas. Something like this:
var baseInstance = new Cls.parent()
I know that I could just call new BaseCls(), but doing it the other way allows me to have only one import.
The superclass is the prototype of the subclass* (which is why superclass static methods are accessible on the subclass), so Object.getPrototypeOf will give you the superclass:
class BaseCls {
constructor() {
console.log("BaseCls");
}
}
class Cls extends BaseCls {
constructor(options){
super(options)
console.log("Cls");
}
}
var base = Object.getPrototypeOf(Cls);
var instance = new base();
You don't have to separate the statements, but if you want to combine them, you have to put () around the call to Object.getPrototypeOf (otherwise new tries to consume it):
var instance = new (Object.getPrototypeOf(Cls))();
And of course, if you wanted to do this generically from a reference to an instance of Cls, it would be:
var superInstance = new (Object.getPrototypeOf(instance.constructor))();
...provided instance doesn't have an own constructor property. Or the rather more convoluted:
var superInstance = new (Object.getPrototypeOf(Object.getPrototypeOf(instance).constructor))();
...if it may have its own constructor property.
* Yes, really. When you use B extends A, there are two parallel lines of inheritance set up: A.prototype is made the prototype of B.prototype, and A is made the prototype of B (whereas in ES5 and earlier, the prototype of a function was always Function.prototype).
Given:
class A {
}
class B extends A {
}
the inheritance looks like this:
B −−−−−−−−−−−−−−> A −−−−−−−−−−−−−−> Function.prototype
B.prototype −−−−> A.prototype −−−−> Object.prototype
class A {
}
class B extends A {
}
console.log(Object.getPrototypeOf(B) === A);
console.log(Object.getPrototypeOf(A) === Function.prototype);
console.log(Object.getPrototypeOf(B.prototype) === A.prototype);
console.log(Object.getPrototypeOf(A.prototype) === Object.prototype);

Categories

Resources