Is there a self pointer to own class? - javascript

Is there some kind of "self" pointer to its own class in JavaScript ?
For example this code has a class called "banana".
I always want Objects of Class "Banana" to be added into the variable "BananaInstances", to never loose the pointer of the new object.
so i got to create a function called "CreateBanana()" which pushs every new object of class "Banana" into the BananaInstances-variable.
var BananaInstances = []
class Banana{
constructor() {
size = "huge"
}
}
CreateBanana()
{
SweetBanana = new Banana()
BananaInstances.push(SweetBanana)
}
CreateBanana()
is there a way to avoid a "CreateBanana"-function and let the constructor of Class "Banana" push itself into "BananaInstances" ?

Within a class, the this keyword is the reference to self.
To keep the references of the created instances of a class - directly within a class use the static keyword.
MDN Classes The static keyword defines a static method for a class. Static methods are called without instantiating their class and cannot be called through a class instance. Static methods are often used to create utility functions for an application.
class Banana {
static instances = [];
size = "huge"
constructor(props) {
Object.assign(this, props);
Banana.instances.push(this);
}
}
const b1 = new Banana();
const b2 = new Banana({size: "normal"});
console.log(Banana.instances);
// [Banana{"size": "huge"}, Banana{"size": "normal"}]
Instead of an Array we could also use new Set
The Set Object lets you store unique values of any type, whether primitive values or object references.
Use static instances = new Set;
and than in the constructor use Banana.instances.add(this);
Notice that the above does not provide an out-of-the-box way to track garbage collected, deleted instances. If the necessity or a Finalizer arises, to remove it from the Set, a new class method like destructor() { Banana.instances.delete(this); } might be required.
class Banana {
static instances = new Set();
size = "huge"
constructor(props) {
Object.assign(this, props);
Banana.instances.add(this);
}
destructor() {
Banana.instances.delete(this);
}
}
const b1 = new Banana();
const b2 = new Banana({size: "normal"});
console.log([...Banana.instances]);
// [Banana{"size": "huge"}, Banana{"size": "normal"}]
b1.destructor(); // Call destructor on b1
console.log([...Banana.instances]);
// [Banana{"size": "normal"}]

Related

Executing a method on all the Class instances in JS

Let's say I have a Class with a method like:
class MyClass {
importantMethod() {
... //any code here
}
}
And let's say I have 10/20/more instances of the Class like:
const inst1 = new MyClass();
const inst2 = new MyClass();
const inst3 = new MyClass();
.... //and more instances here
Is there a way to execute importantMethod() on each instance in a more elegant way than:
inst1.importantMethod()
inst2.importantMethod()
inst3.importantMethod()
.... //and for all the instances
Use forEach
[inst1 , inst2 , inst3].forEach( (item)=> item.importantMethod() )
I assume you want to be able to run a function (at any time, and possibly many times) on all instances of a class that happen to exist at any given moment. YOu could do this by simulating a "private static" list of instances of the class. Each instance gets added to the list on the class's constructor call, and you can supply a function that will iterate over this list:
let MyClass;
{
// this is only visible to functions inside the block
let myClassInstances = [];
MyClass = class {
constructor() {
myClassInstances.push(this);
}
importantMethod() {
console.log(this);
}
}
MyClass.runImportantMethodOnAll = function() {
myClassInstances.forEach(inst=>inst.importantMethod());
}
};
You could use this like:
let x = new MyClass();
let y = new MyClass();
MyClass.runImportantMethodOnAll();
There is no need to attach the runImportantMethodOnAll to MyClass, either. You could store it anywhere.
I think that you have 2 options:
If this can be run on initialization and throws no errors etc and is safe you can run it in the constructor and thus every time there is a new instance it will call it... Not the best practice but possible....
Do something like
const instances = [];
for (let i=0; i<20; i++) {
const classInstance = new MyClass();
classInstance.ImportantFunction();
instance.push(classInstance);
}
This is also sort of a hack but it might make the code a bit cleaner if you have a lot of instances...
If you care about naming the instance then you can change the array in example above to an object and actually put every instance with a named key in the object and then it would be easier to access the instances.
That's from my knowledge at least, I'm not familiar with any "hooks" on class instantiation unfortunately.

Get array in other method in the same class in javascript

I have been looking for an answer on here but i couldn't find any, but anyway my question is how to get an array in a method that has been declared and initialised in an other method but in the same class. I'll make it a bit more clear by demonstrating what i want to achieve and what i have tried so far.
Javascript:
class SomeClass {
method1() {
var array = new array();
//its actually a 2d array and it is being initialised here but for simplicity this isn't
//necessary in the example.
}
method2() {
// --> Here i want to access the array and it's contents.
//I have tried this:
this.array;
//and
array;
}
}
but i got "cannot ready property of undefined" when i tried this.array;
You have to declare the array as an element of the Class, not inside a method, for that, you can use a constructor.
In this link you can see more information.
Here is an example:
class SomeClass {
constructor(someValue) {
// Initialize array or any other atribute
this.arr = new Array(someValue);
}
method1() {
console.log(this.arr);
}
method2() {
console.log(this.arr);
}
}
var instance = new SomeClass('data');
instance.method1();
instance.method2();
The array which is declared in method1 will only be available in that function. There is no way to access local variables of a function in some other function.
The solution could be to use the array as property of instance of class
class SomeClass {
constructor(){
this.array = []
}
method1() {
console.log(this.array);
}
method2() {
console.log(this.array)
}
}
const obj = new SomeClass();
obj.method1();
obj.method2();
Okay so you are making a major mistake, Your concepts of OOP are at stake.
To access array as a property/ instance of a class , You need to declare a constructor it within the class. Somewhat like this
class SomeClass {
constructor(){
this.array = new Array();
}
yourMethod1(){
console.log(this.array); /// You cann access it here and manipulate
}
yourMethod2(){
console.log(this.array); // You can accesss here too and do the same
}
}
Later on you can create an instance of your class like this and access the methods and do whatsoever
let a = new SomeClass();
a.yourMethod1();
a.yourMethod2();

JS create property in a class which is the same type

I have a use case where I want to create a property in a class which is a new instance of the current class. For example:
class Test {
constructor() {
this.prop = new Test()
}
}
const t = new Test();
The problem is that I get Maximum call stack size exceeded. There is any way to do it?
Indeed, the constructor is called again when you do new Test(), so you get an endless call of the constructor.
You probably should do this one by one, and call a method explicitly when you want to "deepen" the object structure with a next instance of Test, like so:
class Test {
constructor() {
this.child = undefined;
}
createChild() {
return this.child = new Test();
}
}
const t = new Test();
const child = t.createChild();
const grandChild = child.createChild();
// ...etc
Now you control how deeply nested this structure should become. Maybe you just want one level deep? Then just call createChild only on the first instance.

How to implement singleton pattern in the following situation?

const instance = Symbol('instance');
class Parent {
number;
constructor() {
const Class = this.constructor;
if (!Class[instance]) Class[instance] = this;
return Class[instance];
}
set_number (number) {
this.number = number;
}
}
class Child extends Parent {
test () { }
}
class Child2 extends Parent {
test () { }
}
const child = new Child();
const parent = new Parent();
const child2 = new Child2();
child.set_number(1);
child.test();
child2.set_number(2);
child2.test(); // child2.test is not a function
parent.set_number(3);
console.log(child.number); // output : 1
console.log(child2.number); // output : 3 (I want it to be 2.)
console.log(parent.number); // output : 3
I implmented Singleton by assigning instances to the constructor.
I want to be implemented in singleton for each of the three classes Parent, Child, and Child2. But there is a problem, when I instantiate Parent class before other classes.
I tried to come up with good idea, but fail. Is there any way I can solve it?
test URL
Class[instance] looks up instance throughout the prototype (inheritance) chain. So in case of Child2 it starts with Child2, and if there is no property it continues with Parent, then with Object. The result is that you return an instance of Parent when you want create the instance of Child2.
Instead of checking the existence of the property by using a lookup, you should use hasOwnProperty():
if (!Class.hasOwnProperty(instance)) Class[instance] = this;
That means if Child2 itself(!) does not have an instance, then assign one to it.

Referencing static members from instance method on dynamically extended JS class

I have a base ES6 class that I dynamically extend given a configuration object, like so:
class Model {
constructor () {
// ...
}
save () {
// ...
}
}
function createModelFromConfig (config) {
const Impl = class extends Model {};
Object.assign(Impl, config);
return Impl;
}
const User = createModelFromConfig({store: new DbStore()});
In the save() method on the abstract Model, I'd like to reference the static object store, which will exist on the class that extends Model. This means, of course, that I need to reference a static member but the extended class is anonymous.
Just in a quick test using the Chrome console, I tried
function X () {}
X.prototype.doSomething = function () { console.log(this.constructor); };
function Y () {}
Y.prototype = Object.create(X.prototype);
new Y().doSomething(); // function X () {}
I don't know if this is a reliable test, but it appears that this.constructor does not reference the Impl that I extended, but instead the original base class, which isn't helpful.
A less elegant way is to add Impl.prototype.Impl = Impl; so I can use this.Impl.store in my save function, but it'd be preferable if I could access the static members of the Impl class without this.
Is my prototypal test in the console inadequate? Or is there any other way to access the constructor class in an instance method from an inherited method?
In my testing, I've concluded that Y.prototype = Object.create(X.prototype); is not an adequate equivalent to the ES6 extends implementation.
In running in the Node REPL:
class X {
constructor () {}
save () { console.log(this.constructor.z); }
}
class Y extends X {}
Y.z = 'z';
new Y().save(); // 'z'

Categories

Resources