i am having some issues learning class methods syntaxes... there are a few and I dont know if they have different behaviours or if they are just equivalent/updated versions of one another.
is my thoughts real?
class Person {
constructor(name) {
this.name = name
}
instanceMethod() { // this.
console.log('hello there')
}
}
Person.prototype.instanceMethod = () => { //equivalent to this?
}
const person = new Person()
person.instanceMethod // so we call the "person.prototype.instanceMethod'' in the instance of the class
// ... //
class Person {
constructor(name) {
this.name = name
}
static staticMethod() { // this.
console.log('hello there')
}
}
class OtherPerson extends Person {
}
Person.staticMethod = () => { // is equivalent to this?
}
const person = new Person()
Person.staticMethod() // so we call the static method in the Parent Class
OtherPerson.staticMethod //or a child class of that Parent Class.
or to call in the child class of the class you have to provide their own static methods?
class OtherPerson extends Person {
(... constructor and stuff...)
staticMethod() { console.log('hello there') } // defining their own static methods.
staticMethod() { super.staticMethod() } //or make this as well... both with same results
}
Here is my parent.class.js
class ParentClass {
constructor() {
}
}
module.exports = { ParentClass };
child.class.js
const { ParentClass } = require('./parent.class');
class ChildClass extends ParentClass {
constructor(index) {
super();
this.index = index;
}
showIndex() {
console.log(this.index)
}
}
module.exports = { ChildClass };
And index.js where I'm using the child class
const ChildClass = require('./child.class');
ChildClass(1).showIndex(); // This obviously is not working
NOTE: this is only an example. In the actual project I'm not able to use ES6 module import
My question is how can I pass parameters to child class instance in my index.js?
In case of ES6 I would be able to do something like this:
import ChildClass from './child.class.js'
const ChildClass = new ChildClass(1)
ChildClass.showIndex(); // outputs 1 ...I guess??
How do I pass argument to the childclass?
The problem is
module.exports = { ChildClass };
and
const ChildClass = require('./child.class');
You're exporting an object which has a property of ChildClass there, and then you're importing the whole object and trying to call it. But objects aren't callable; you aren't referring to the ChildClass class.
Just like you destructured the ParentClass with
const { ParentClass } = require('./parent.class');
Either destructure the ChildClass:
const { ChildClass } = require('./child.class');
Or assign the ChildClass to the module.exports:
module.exports = ChildClass;
And then you'll be able to create instances of the ChildClass and call methods on the instance:
const child = new ChildClass(1);
child.showIndex();
I am trying understand mixins in javascript and all the examples and articles i have read so far talk about adding methods and not properties.
I have found Alex Jover Morales' article really useful and i have slightly modified his example to include an additional mixin and constructors with new properties within the mixins here.
Is what i have done below an anti-pattern?
Is there a problem with having a constructor and properties within a mixin?
Is there a problem with calling super() within each mixin's contructor?
const PlayMixin = superclass => class extends superclass {
constructor(args) {
let { favouriteGame } = args
super(args);
this.favouriteGame=favouriteGame;
}
play() {
console.log(`${this.name} is playing ${this.favouriteGame}`);
}
};
const FoodMixin = superclass => class extends superclass {
constructor(args) {
let { genericFood } = args
super(args);
this.genericFood=genericFood;
}
eat() {
console.log(`${this.name} is eating ${this.genericFood}`);
}
poop() {
console.log("Going to 💩");
}
};
class Animal {
constructor(args) {
let {name} = args
this.name = name
}
}
class Dog extends PlayMixin(FoodMixin(Animal)) {
constructor(...args) {
super(...args)
}
bark() {
console.log("Woff woff!")
}
haveLunch() {
this.eat();
this.poop();
}
}
const jack = new Dog({name:"Jack", genericFood:"lobster",
favouriteGame:"chess"});
jack.haveLunch();
jack.play();
.as-console-wrapper { max-height: 100%!important; top: 0; }
Is what i have done below an anti-pattern?
No, it is not.
Is there a problem with having a constructor and properties within a mixin?
No, as long as you call super(...) in a manner that it works for all mixed in classes.
Is there a problem with calling super() within each mixin's contructor?
No, super always points to the extended class, there isno problem in calling that constructor.
I have TypeScript (JavaScript) class like this:
import * as React from 'react'
export default
class StyleableComponent<PROPS, STATE> extends React.Component<PROPS, STATE> {
protected classes: any
static style: any
someMethod() {
const ctor = this.constructor
console.log(this.constructor.style)
}
}
and TypeScript throws this error:
ERROR in ./src/StyleableComponent.ts
(11,38): error TS2339: Property 'style' does not exist on type 'Function'.
But, obviously, you can see that static style: any is declared in the class definition.
So, how do we work with this.constructor properly? Note, this.constructor can be the constructor of a class that extends StyleableComponent, so this.constructor may not be === StyleableComponent, but it should have the style property because it extends from StyleableComponent.
For example,
interface P {...}
interface S {...}
class Foo extends StyleableComponent<P,S> {...}
console.log(new Foo)
^ this.constructor will be Foo, and the StyleableComponent class needs to look at Foo.style.
So how do I do this? Do I need to use a extra template type parameter somehow?
Static Property V.S Instance Property Inheritance
If you want read static property from subclass,you can do it with 3 ways.for more details you can see Test section.
because Object.getPrototypeOf(..)'s return type is any, so you can access style directly,for example:
someMethod() {
let style = Object.getPrototypeOf(this).constructor.style;
}
because this.constructor's return type is a Function, so you must assign it to a any variable at first,for example:
someMethod() {
let cotr:any=this.constructor;
let style = cotr.style;
}
because Function is an interface you can expand it in typescript,for example:
declare global{
interface Function{
style:any;
}
}
someMethod() {
return this.constructor.style;
}
and you can also do it with replace static property with instance property instead.if you want read subclass style property you must define the property on constructor,then the subclass can choose define its style by pass the style to the superclass or not at all.for example:
constructor(protected style:any="default"){
}
the interesting is that the subclass behavior are all the same except the style property.In design view, if you use the static style properties you must define another subclass to achieve it,this will tends to many subclass with diff styles.but when use instance property style,you can do it by pass the style with optional for different style only.for example:
let bar=new Bar();//use parent's style
let baz=new Bar(null,null,"baz");//use it owned style
and you can also reject others to pass their style by pass the style in constructor of the subclass.for example:
constructor(){
super("style");
}
Tests
import * as React from 'react';
declare global {
interface Function {
style: any
}
}
describe('static inheritance', () => {
class StyleableComponent<P, S> extends React.Component<P, S> {
protected classes: any;
static style: any;
constructor(props?: P, context?: any, public style: any = "default") {
super(props, context);
}
someMethod() {
//dangerous if subclass not define static style property
//todo:the 1st approach
// let style = Object.getPrototypeOf(this).constructor.style;
// return style;
//todo:the 2nd approach
// let cotr: any = this.constructor;
// return cotr.style;
//todo:the 3nd approach,you must declare style in Function interface
return this.constructor.style;
}
}
class Foo extends StyleableComponent<any, any> {
static style = "foo";
constructor(props?: any, context?: any) {
super(props, context, Foo.style);
}
}
class Bar extends StyleableComponent<any, any> {
}
test('access style from subclass', function () {
let foo = new Foo();
expect(foo.someMethod()).toBe(Foo.style);
});
test('return undefined if subclass not define style', function () {
let bar = new Bar();
expect(bar.someMethod()).toBeUndefined();
});
test('replace static style with instance property', function () {
let foo = new Foo();
let bar = new Bar();
let baz = new Bar(null, null, "baz");
expect(foo.style).toBe("foo");
expect(bar.style).toBe("default");
expect(baz.style).toBe("baz");
});
});
I have a base class :
class Base {
constructor() {
this.name = "base_class"
}
getBaseName() {
return "base"
}
}
and a Derived class
var _ = require('lodash');
class Derived {
constructor() {
this.name = "derived"
}
getDerivedName() {
return "derived"
}
}
_.extend(Derived.prototype, Base)
I was expecting to have getBaseName available in the derived class. But its not the case. What should I do for that? What am I missing?
var derived = new Derived();
console.log(derived.getBaseName)
-- undefined
Why are you using lodash to extend ES6 classes? Can't you just use the extends keyword?
class Derived extends Base {
constructor() {
super();
this.name = "derived"
}
getDerivedName() {
return this.name;
}
}