I'm wondering if there is a standard way to re-initialize, or re-construct a class instance without creating a new instance all together.
Let's say I have a TestClass instance:
class TestClass {
constructor() {
this.x=0;
this.y=50;
this.z=200;
}
}
var testClassInstance=new TestClass();
And basically, overtime I tweak some of it's values.
testClassInstance.x+=250;
testClassInstance.y-=20;
Then later on I want to reset all of its values to whatever was defined when the instance was created. I'm wondering if there is a way to then basically reinitialize it, without creating an entirely new instance?
Is something like
testClassInstance.constructor()
safe and reliable?
class TestClass {
constructor() {
this.reset();
}
reset(){
this.x=0;
this.y=50;
this.z=200;
}
}
const myTestClass = new TestClass();
myTestClass.x = 5;
console.log(myTestClass.x); // 5
myTestClass.reset();
console.log(myTestClass.x); // 0
This answer was generated because of the first version of this question.
Your class is never modified. The class is an implementation, what you modify are the instances created using that implementation.
Look this code snippet:
class TestClass {
constructor() {
this.x=0;
this.y=50;
this.z=200;
}
}
var testClassInstance=new TestClass();
testClassInstance.x+=250;
testClassInstance.y-=20;
console.log(testClassInstance.x);
console.log(testClassInstance.y);
var anotherTestClassInstance=new TestClass();
console.log(anotherTestClassInstance.x);
console.log(anotherTestClassInstance.y);
See? the new object has the initial values declared in TestClass's constructor.
Related
I am looking for a way to call new this from within a class method.
class Example {
fork() {
return new this();
}
}
const x = new Example().fork(); // instance of example
class Alpha extends Example {}
const x = new Alpha().fork(); // expected instance of Alpha but is example
I assume you mean you want to call new this.constructor() (see MDN doc) and not new this(), since it is vanishingly rare that the instance of a class will also be a class constructor. At runtime this is all you need.
Unfortunately the typing for constructor in TypeScript is messy. See microsoft/TypeScript#3841 for details, but the main issue is that since subclass constructors can require a different set of arguments from their superclass constructors, if this.constructor were strongly typed, then many class hierarchies would fail to form a valid subtype hierarchy and would therefore violate substitutatibility.
So in TypeScript, constructor is typed only as Function, and therefore new this.constructor() will yield an error:
return new this.constructor(); // error!
// This expression is not constructable.
In order to tell the compiler that this.constructor is a zero-arg constructor function, you'll have to either use a type assertion like this:
class Example {
fork(): this {
return new (this.constructor as new () => this)()
}
}
or add a strongly-typed constructor property declaration to your class like this:
class Example2 {
['constructor']: new () => this
fork(): this {
return new this.constructor()
}
}
Both solutions work for your presented example use case:
const x = new Example().fork(); // Example
class Alpha extends Example { }
const y = new Alpha().fork(); // Alpha
But neither solution will prevent you from calling fork() on an instance of a subclass whose constructor requires a parameter
class Blop extends Alpha {
constructor(x: string) {
super();
console.log(x.toUpperCase());
}
}
const z = new Blop("oops").fork(); // error at runtime!!
Without a good solution to microsoft/TypeScript#3841, I think this might be the best you can get.
Playground link to code
I am working on a large project where I have multiple managers to handle different tasks, I need an only a single object of these managers to be created when I start the app,
I came across this method of Singleton creation
class QuestionnaireManager {
constructor() {
if (this.instance) {
return;
}
this.instance = this;
}
}
Is this an acceptable way, is there any downside, I am coming from JAVA Kotlin background and this seems to simple to be true where we have so much to deal in case of singletons in other languages. (Most of those cases have to deal with multi-threading but as JS is single-threaded so I think this would be sufficient way)
Still need opinion on best practices, or any other Dependency Injection methods where we don't even rely on Singleton but create the object once and reuse all over the project with dependency injections.
I would like to know the opinion of sensie in JS.
That ain't the right way to implement Singleton in ES6. The correct way:
class QuestionnaireManager {
constructor() {
if (QuestionnaireManager._instance) {
throw new Error("Singleton classes can't be instantiated more than once.")
}
QuestionnaireManager._instance = this;
// ... your rest of the constructor code goes after this
}
}
var managerOne = new QuestionnaireManager()
var managerTwo = new QuestionnaireManager() // Throws error
Or, if you don't want an error to be thrown on second instance creation you can just return the last instance, like so:
class QuestionnaireManager {
constructor() {
if (QuestionnaireManager._instance) {
return QuestionnaireManager._instance
}
QuestionnaireManager._instance = this;
// ... your rest of the constructor code goes after this
}
}
var managerOne = new QuestionnaireManager()
var managerTwo = new QuestionnaireManager()
console.log(managerOne === managerTwo) // logs "true"
// Singleton.js
class Singleton {
constructor(){
if(Singleton._instance){
console.warn("already created!");
return Singleton._instance;
}
Singleton._instance = this;
console.log("singleton created");
this._createdTime = new Date();
}
static instance() {
if(!Singleton._instance){
return new Singleton();
}
return Singleton._instance;
}
createdTime() {
return this._createdTime.toISOString();
}
}
Singleton._instance = null;
export default Singleton;
// main.js
import Singleton from "./Singleton"
const a = new Singleton();
const b = new Singleton();
const c = Singleton.instance();
console.log(a.createdTime());
console.log(b.createdTime());
console.log(c.createdTime());
Output would be
In javascript you can export an instance of a class to make a singleton
// questionnaire-manager.js
class QuestionnaireManager {
constructor() {
}
}
module.exports = new QuestionnaireManager()
Then when you call require('questionnaire-manager') you'll always get the same instance.
Like Mikel B.'s answer only in a shorter syntax
module.exports = new class foo {..}
You need a static property, not instance property this.instance. It will be accessable by QuestionnaireManager.instance reference. But... it is sooo rare case to implement classical GOF singleton in Javascript... kind of enforcing yourself to develop UI in vim and feel yoursefl as "true develper" :)
This question already has answers here:
JS call static method from class
(7 answers)
Closed 4 years ago.
Is it possible to access the class itself inside of a classes function:
class MyClass {
static get myFunction() { return "foo"; }
constructor() {
console.log(MyClass.myFunction); // "foo" -- it works when using its name. This is what we want but without using the name
console.log(this.myFunction); //undefined
console.log(this.prototype.myFunction); //Cannot read property 'myFunction' of undefined
}
}
new MyClass();
Is it possible to achieve the same as you do with MyClass.myFunction() and access the static methods without using the name of the class (in this case without using MyClass in this example?
Something like this.master.myFunction() (I’m just making master up here it’s obviously not called master)
JSBin: https://jsbin.com/hawituxosu/1/edit?js,console
Is that even possible? Thank you!
you can use constructor for this
Returns a reference to the Object constructor function that created the instance object
The constructor property has three purposes:
1. Get the class object.
2. Create an new instance
3. Invoke super constructor
class MyClass {
static get myFunction() { return "foo"; }
constructor() {
console.log(this.constructor.myFunction);
}
}
new MyClass();
an option you can do here is to call static method inside an instance method and call that instance method
class MyClass {
static get myFunction() { return "foo"; }
constructor() {
console.log(MyClass.myFunction); // "foo" -- whith using its name it works. This is what we want but without using the name
console.log(this.constructor.myFunction);
}
myFunction2() {
return this.constructor.myFunction();
}
}
const master = new MyClass();
master.myFunction2();
this.constructor.myFoo
The constructor property helps you here
You could work around getting to the class name using:
this.__proto__.constructor.name // MyClass
class MyClass {
static get myFunction() { return "foo"; }
constructor() {
console.log(eval(this.__proto__.constructor.name + ".myFunction")); //foo
}
}
new MyClass();
I have an Octree class. A key feature of an Octree is that it can create its own children.
class Octree {
...
createChildren(){
...
/* for each of the 8 new children*/
this.children.push(new Octree(/*someargs*/))
...
}
}
Now I want to inherit off of the Octree class, however, I also want the children to become the inherited class. For example class LODWorldTree extends Octree, to additionally contain some renderer data for a game. However, if I call LODWorldTree.createChildren(), then LODWorldTree.children will be an array of Octrees instead of LODWorldTrees.
What is the best way to fix this problem? While writing this it occured to I could store Octree.myClass = /*some inherited class*/, and manually set this variable for all classes that inherit from Octree. Is there a better way to do something like this? Maybe with this.prototype?
You can utilize the fact that each object has a reference to it's own constructor via the prototype:
class A {
constructor() {
this.val = 1;
this.children = [];
this.typeName = `I'm A`;
}
addSelfChild() {
this.children.push(new this.constructor(this.val + 1));
}
}
let a = new A(1);
a.addSelfChild();
a.addSelfChild();
console.dir(a);
class B extends A {
constructor(val) {
super(val);
this.typeName = `I'm B`;
}
}
let b = new B(1);
b.addSelfChild();
b.addSelfChild();
console.dir(b);
Try to use constructor attribute:
this.children.push(new this.constructor(/*someargs*/));
this.constructor is the reference for constructor for current object, so invoking it will produce new instance of the same class
I try to extend a class with another, who has its constructor overrode, but when i instance this class, it doesn't have its own methods, but has its own properties.
Here's an example which doesn't work properly:
class A {
constructor () {
return {
pi: 3.14
}
}
}
class B extends A {
constructor () {
super();
this.c = 10;
}
d () {}
}
let b = new B();
console.log(b);
Here, b is :
Object {
c:10,
pi:3.14
}
So why the 'd' method is missing ?
EDIT:
Here is a concrete case:
I need to extend a class with HTMLElement, which i can instance and use like html element without registering with document.registerElement.
My code is:
class Element{
constructor(){
return document.createElement('div');
}
}
class Editor extends Element{
constructor(){
super();
}
}
and i want to use my class like this:
let editor = new Editor();
document.querySelector('body').appendChild(editor);
ECMAScript6 class methods are methods of an object's prototype object. You will find the method not in the object itself, but in obj.__proto__.
https://reinteractive.com/posts/235-es6-classes-and-javascript-prototypes
Here you can see and maybe understand what is going on internally with prototyped objects. And yes, the ES6 syntax is just a syntax change, not a new technology.