Javascript execute function in es6 class on extend - javascript

How can I execute a function that is aware of a newly created class's name which is derived from a certain parent at the time that the class is extended?
What I currently do:
class component {
constructor() {
// this.constructor.name returns the derived class name on instantiation
// we need to register class components derived from component
registerIfUnknown(this.constructor.name);
}
}
However this means the registerIfUnknown function will be called every time we create a new instance of any subclasses of component. Is there a way to execute a method/function that understands what the class's name is whenever the component class is extended?

Related

JavaScript - Create elements using web component class

I have a web component that only works when some properties are set, when I create the component with Document.createElement() I can't pass properties then an error happens in my component.
Is it possible to create the component by creating an instance of the component class or something similar and be able to pass parameters to it's constructor?
customElements.define('x-card', class extends HTMLDivElement {
//...
}, { extends: 'div' });
You can create a new instance using new WCard. This requires having access to the class though.
Please note that custom element names preferrably should not start with x-.
So change your code:
export class WCard extends HTMLDivElement {
//...
}
customElements.define('w-card', WCard, { extends: 'div' });
window.WCard = WCard;
This allows you to call new on the class globally, or if your code imports the class.
const wcard = new WCard(...args);

Call parent function in parent class instead of child (same names) javascript

I have two functions with same names. One inside child class and one inside parent.
I thought If i call method in parent class that parent's function will be invoked.
But it looks it doesn't work like this and invokes child function.
So my question is how to invoke parent function in parent class if i have another with same name in child class.
I would like to get 'Parent' and 'Child', but i get 2 times 'Child'
class Parent {
constructor() {
this.init()
}
init() {
console.log('Parent');
}
}
class Child extends Parent {
constructor() {
super();
this.init()
}
init() {
console.log('Child');
}
}
new Child();
this is referring to the child instance, and inherits its .init method that shadows the .init method inherited from the parent. To refer to that explicitly, you'd write
class Parent {
constructor() {
Parent.prototype.init.call(this)
}
init() {
console.log('Parent');
}
}
But this is a really bad idea, both to override a method where the overriding one shouldn't be called, and in general to call overrideable methods in the constructor. In your case, just do all your work inside your constructor instead and drop the init method altogether.
As parent constructor call init() already, child constructor should not call init() any more.
Instead, child init() can optionally call parent init().

Making a new ES6 Object in another Object's constructor fails

Edit: this question is different from How to extend a class without having to using super in ES6? - although the answers are related, this is very obviously a different question. It relates to a specific error, and the two main classes involved Person and CreationEvent don't actually inherit from each other.
I have two ES6 classes, Person and CreationEvent (CreationEvent inherits from Event). I wish to to make a new CreationEvent when I make a new Person (as the CreationEvent is part of the events in the history of person's account).
Running new CreationEvent() on it's own works fine. However I can't run new Person().
Even with reduced version of the code still fails:
class Event {
constructor() {
this.time = Date.now()
this.tags = []
}
}
class CreationEvent extends Event {
constructor() {
this.description = "Created"
}
}
class Person {
constructor(givenName, familyName, email) {
var creationEvent = new CreationEvent()
}
}
Running new Person() returns
ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor
How do I make a new ES6 Object in another Object's constructor?
You need to call super() in the CreationEvent class because it extends the Event class and needs te be initialized. Like this:
class CreationEvent extends Event {
constructor() {
super();
this.description = "Created"
}
}

Wrapping a constructor with javascript method decorator

Referenced:
Override constructor with an class decorator?
http://blog.wolksoftware.com/decorators-metadata-reflection-in-typescript-from-novice-to-expert-part-ii
I'd like to wrap a classes constructor with a custom one when applying a method decorator (ie in the same way you could do with a class decorator). I require this as I have another component that will call into the class, and will execute the method that was decorated. Its not hard to have the component execute the method that was decorated, however because the decorator is run before the class is instantiated the decorated method will not be associated with a class instance and therefore will not have access to any of the classes state (ie this == undefined). So I want to be able to provide the method reference to the component during class instantiation (ie constructor) so that it is bound to the current instance.
So I'd like to do this (typescript):
class Foo {
constructor(private value) { }
#execute
bar() {
return this.value;
}
}
Which would have the same affect as doing this:
class Foo {
constructor(private value) {
StaticComponent.AddReference(this.bar().bind(this));
}
bar() {
return this.value;
}
}
If my other component has a reference to bar() it should be able to execute it with bar having full access to its instance.
I've tried to override the prototype of the target etc in a similar way you might do so for a class decorator, but couldn't get that to work.

what does super() do without any arguments?

I'm learning react from the docs, but not sure what the super() does in this example. Usually, doesn't it take the arguments that are passed to making a new instance and then calls React.Component's constructor method to incorporate these arguments into the instance? What does it do without any arguments?
class LikeButton extends React.Component {
constructor() {
super();
this.state = {
liked: false
};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState({liked: !this.state.liked});
}
render() {
const text = this.state.liked ? 'liked' : 'haven\'t liked';
return (
<div onClick={this.handleClick}>
You {text} this. Click to toggle.
</div>
);
}
}
ReactDOM.render(
<LikeButton />,
document.getElementById('example')
);
In ES6, derived classes have to call super() if they have a constructor. In react, all components extend from the Component class.
You don't actually need a constructor for every ES6/react class. If no custom constructor is defined, it will use the default constructor. For base classes, it is:
constructor() {}
And for derived classes, the default constructor is:
constructor(...args) {
super(...args);
}
You also need to call super() before accessing this, since this is not initialized until super() is called.
There are a few reasons to use a custom constructor in react. One is that you can set the initial state within the constructor using this.state = ... instead of using the getInitialState lifecycle method.
You can also bind class methods inside the constructor with this.someClassMethod = this.someClassMethod.bind(this). It's actually better to bind methods in the constructor since they will only be created once. Otherwise if you call bind or use arrow functions to bind methods anywhere outside the constructor (like in the render method), it will actually end up creating a new instance of the function on every render. Read more about that here.
If you want to use this.props in the constructor, you need to call super with props as an argument:
constructor(props) {
super(props);
this.state = {count: props.initialCount};
}
If you don't, then this.props is undefined in the constructor. However, you can still access this.props anywhere else in the class outside the constructor without needing to do anything with it in the constructor.
The super keyword in JavaScript is used in order to call the methods of the parent class. By itself, super() is used within a constructor function to call the parent constructor function. For example:
class Animal {
constructor(age) {
console.log('Animal being made');
this.age = age;
}
returnAge() {
return this.age;
}
}
class Dog extends Animal {
constructor (age){
super(age);
}
logAgeDog () {
console.log(`This dog is: ${ super.returnAge()} years old`);
}
}
const dog = new Dog(5);
console.log(dog);
dog.logAgeDog();
In this example we have a Dog class which extends an Animal class. The Dog class uses the super keyword twice. The first occurence is in the constructor, when super() is used in the constructor it will call the parent class constructor. Therefore we have to give the age property as an argument to it. Now the Dog successfully has an age property.
We can also use super outside of the constructor in order to access the parent's 'class' (i.e. prototype) properties and methods. We use this in the logAgeDog function located in the Dog class. We use the following code:
super.returnAge();
You should read this as:
Animal.returnAge(); // superClass.returnAge()
Why do I need this in React?
You need the super() keyword in React only when implementing a constructor. You have to do the following:
constructor(props) {
super(props);
// Don't call this.setState() here!
}
the parent class which is named Component needs to do some initialization on its own in order for React to work fine. If you implement a constructor without a super(props) call this.props in Component will be undefined which can lead to bugs.

Categories