class Parent {
print() {
console.log('hey i am parent');
}
}
class Child extends Parent {
constructor() {
super();
}
print() {
console.log('hey i am child');
}
}
x = new Parent();
console.log(Object.getPrototypeOf(x))
x.print();
Though the [[prototype]] of x is an empty object but still It can access the print() function which is defined in class Parent.
I cannot understand why Object.getPrototypeOf(x) is an empty object.
It's in there, just non-enumerable. Try this:
Object.getOwnPropertyNames(Object.getPrototypeOf(x));
// ["constructor", "print"]
class Parent {
print() {
console.log('hey i am parent');
}
}
class Child extends Parent {
constructor() {
super();
}
print() {
console.log('hey i am child');
}
}
x = new Parent();
console.log(Object.getOwnPropertyNames(Object.getPrototypeOf(x)));
x.print();
What makes you think it's empty? It does have constructor and print properties, they are however not enumerable and not displayed by default on the console. (And of course it does have a [[prototype]] link to Object.prototype, but how/whether that is displayed depends on your console as well).
To inspect them, have a look at Get functions (methods) of a class.
Related
I would like to call "super" from a bound function.
Here is my use case: I have many child classes from different parents. I'd like to bind the same function to all of them (instead of copy pasting it). That function needs to call the "super" version of that same function.
Example:
class Parent {
func() {
console.log("string1");
}
}
function boundFunc() {
super.func();
console.log(this.string2);
}
class Child extends Parent {
constructor() {
super();
this.string2 = "string2"
this.func = boundFunc.bind(this);
}
}
const child = new Child();
child.func();
I would like to obtain result:
string1
string2
I get this result instead (unsurprisingly, I'd day):
"SyntaxError: 'super' keyword unexpected here".
I've tried to pass the super function as an argument to bind. Like this:
function bindedFunc(thisArg, oriFunc) {
oriFunc();
console.log(this.string2);
}
class Child extends Parent {
constructor() {
super();
this.string2 = "string2"
this.func = bindedFunc.bind(this, super.func);
}
}
Result (oriFunc happens to be undefined):
TypeError: oriFunc is not a function
Any solution? Thank you
Instead of super, you can use Object.getPrototypeOf twice: once to navigate from the instance to its internal prototype (which is Child.prototype), and once to navigate from that to its internal prototype (which is Parent.prototype):
class Parent {
func() {
console.log("string1");
}
}
function boundFunc() {
Object.getPrototypeOf(Object.getPrototypeOf(this)).func();
console.log(this.string2);
}
class Child extends Parent {
constructor() {
super();
this.string2 = "string2"
this.func = boundFunc.bind(this);
}
}
const child = new Child();
child.func();
I've recently started to learn about Classes in javascript and while reading some really interesting stuff I thought of trying some of my own ideas.
If you have a parent class of Parent in which you have a method of logSomething```` and a child class ofChild, with which you doclass Child extends Parent, how can you then execute the inherited method from the parent class,logSomething```, inside of the child class?
If you define a method inside of the Child class and add this.logSomething() to that method, whenever the method from the child class is called, the inherited logSomething function will indeed run, but apart from that I haven't found any way of executing the logSomething directly inside of that child class.
I've tried this.logSomething(), I've tried adding it to a object, self executing (IIFE) function and everything I could thing of but to no result.
class Parent {
constructor() {}
logSomething() {
console.log('I am logging something')
}
}
class Child extends Paren {
logSomething() // This does not work
}
Currently doing this does not work, if throws a error referring to the fact that it things your trying to define a function.
I know it should be possible in some way, if I'm not mistaking React uses something similar with life-cycle methods right? Such as componentWillMount.
How would one go about doing this?
First error is that you are extending Paren instead of Parent.
Also you cannot just throw a random statement inside in a class. It needs to be inside a function.
If you want it to run whenever you create an instance of that class it should be inside the constructor or a function that gets called by it. (note that you need to call super() at the start of the constructor.
Finally, you still need to use this.logSomething or this.logSomething
class Parent {
constructor() {}
logSomething() {
console.log('I am logging something');
}
}
class Child extends Parent {
constructor() {
super();
this.logSomething(); // Will use Parent#logSomething since Child doesn't contain logSomething
super.logSomething(); // Will use Parent#logSomething
}
}
new Child();
class Parent {
constructor() {}
logSomething() {
console.log('Parent Logging Called');
}
}
class Child extends Parent {
constructor() {
super();
this.logSomething(); // Will call Child#logSomething
super.logSomething(); // Will call Parent#logSomething
}
logSomething() {
console.log('Child Logging Called');
}
}
new Child();
You could also do this:
class Parent {
constructor() {}
logSomething() {
console.log('Parent Logging Called');
}
}
class Child extends Parent {
logSomething() {
console.log('Child Logging Called and ...');
// Careful not use this.logSomething, unless if you are planning on making a recursive function
super.logSomething();
}
}
new Child().logSomething();
You can call any function or use any property of the parent class using this, as long as the new class doesn't have its own definition for that property.
Look here for more information.
class Parent {
constructor() {}
logSomething() {
console.log('I am logging something')
}
}
class Child extends Parent {
logSomething() {
super.logSomething(); // Call parent function
}
}
a) you can't call a function there, you can call a function within a function declared in a class
b) you need to use this.logSomething()
example:
class Parent {
constructor() {}
logSomething() {
console.log('I am logging something')
}
}
class Child extends Parent {
fn() {
this.logSomething() // This does work
}
}
new Child().fn()
See other answers for when fn is called logSomething in the child class - then you'd need super.logSomething() to call the "parent" logSomething instead of the child logSomething
I'm trying to write a subclass using the es6 class syntax. The subclass has some complicated logic to perform before calling the superclass constructor, so I tried factoring it out into a function. However, this seems to be impossible since this is not defined until after super() is called.
I've tried simply calling super() twice, once at the start of the constructor and once at the end, but it feels wrong and wastes the work that the superclass constructor does the first time.
class Parent {
constructor(x) {
console.log('some expensive thing with ' + x);
}
}
class Child extends Parent {
constructor() {
let x = this.f();
super(x);
}
f() {
// complicated logic
return 3;
}
}
let c = new Child();
Running the code as written results in ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor at new Child. Removing this and attempting to call f() results in ReferenceError: f is not defined at new Child.
Is there any way to factor the subclass constructor logic somewhere else, even if it's okay if this isn't bound?
I would use an initialization function separate from the constructor as that give you more control over when/if parent initialization happens.
class Parent {
constructor(x) {
this.init(x);
console.log("parent constructor does other stuff");
}
init(x) {
console.log("parent init runs")
}
}
class Child extends Parent {
constructor(x) {
super(x);
}
init(x) {
console.log("child init runs");
super.init(x); // This call is optional if you don't want to run the parent's init code
}
}
let c = new Child();
Using a static method could be a solution.
class Parent {
constructor(x) {
console.log('some expensive thing with ' + x);
}
}
class Child extends Parent {
constructor() {
let x = Child.f();
super(x);
}
static f() {
// complicated logic
return 3;
}
}
let c = new Child();
I don't want my parent class to be too long so I separate some methods from it and create child class.
However I don't want to use child class as a instance I want it to be used only by parent class.
class Parent {
parentMethod() {
this.foo(); // execute from parent
}
}
class Child extends Parent {
foo() {
console.log('foo!');
}
}
const parent = new Parent();
parent.parentMethod(); // execute parent method which execute child method
this cause:
Uncaught TypeError: this.foo is not a function
I don't want my parent class to be too long so I separate some methods from it
Ok.
So I create child class, however I don't want to use child class as a instance.
No, subclassing is the wrong approach here. Especially if you don't want to instantiate the subclass, it's not even a solution to your problem.
To separate units of code, factor them out into separate functions. Those don't need to be linked to the caller through inheritance, and don't need to be methods of a class at all. Just write
class MyClass {
myMethod() {
foo();
}
}
function foo() {
console.log('foo!');
}
const instance = new MyClass();
instance.myMethod();
Or compose your object of multiple smaller helpers:
class Outer {
constructor() {
this.helper = new Inner();
}
myMethod() {
this.helper.foo();
}
}
class Inner {
foo() {
console.log('foo!');
}
}
const instance = new Outer();
instance.myMethod();
If you want to use the Parent class in the subclass, Child class, then you need to do the following:
class Parent {
foo() {
console.log('foo!');
}
}
class Child extends Parent {
constructor() {
super();
}
}
let c = new Child(); //instantiate Child class
c.foo(); // here you are calling super.foo(); which is the Parent classes method for foo.
//foo!
The super keyword is used to access and call functions on an object's
parent.
How to use super
Or, alternatively, if you'd rather create a method on the child class that wraps the parent method of foo, rather than accessing it by instantiating the parent class via calling super in the child constructor:
class Parent {
foo() {
console.log('foo!');
}
}
class Child extends Parent {
method() {
this.foo();
}
}
let c = new Child();
c.method();
I have a class Parent (defined using the class declaration, though I'm aware this is primarily syntactic sugar), and multiple classes (Child1, Child2, etc) that extend it. The child classes have a static property assigned to them (outside of their declarations - as far as I'm aware there is no way to assign a static property within a class declaration).
I would like to access the a static value of any child class from the parent class, such as in the method getStaticValue().
class Parent {
constructor() {
//Do parent stuff
}
getStaticValue() {
return "The value of staticValue is " + this.staticValue;
}
}
class Child1 extends Parent {
constructor() {
super();
//Do child1 stuff
}
}
Child1.staticValue = "Child1";
class Child2 extends Parent {
constructor() {
super();
//Do child2 stuff
}
}
Child2.staticValue = "Child2";
I want to access the value of staticValue of any arbitrary child from the parent class, however attempting to do so as written above always returns undefined. In other words:
let parentStaticValue = new Parent().getStaticValue();
//Desired output = "The value of staticValue is undefined"
//Actual output = "The value of staticValue is undefined"
let child1StaticValue = new Child1().getStaticValue();
//Desired output = "The value of staticValue is Child1"
//Actual output = "The value of staticValue is undefined"
let child2StaticValue = new Child2().getStaticValue();
//Desired output = "The value of staticValue is Child2"
//Actual output = "The value of staticValue is undefined"
Is there a way to access the a static value of a child class from the parent class, without having to know the name of the child class in every case?
You can use the constructor property of a class instance to access static properties held as properties of the instance's constructor function, as in:
class Parent {
constructor() {
//Do parent stuff
}
getStaticValue() {
return this.constructor.staticValue;
}
}
Warning
The constructor property of an object is inherited from the prototype chain.
Class syntax made the prototype object property of a class constructor's function object non-configurable (good), but left the constructor property of this same prototype object writable (bad).
NEVER change the constructor value of class constructors' prototype objects if you know what's good for you want class extensions to work correctly.
Demo:
class Parent {
constructor() {
//Do parent stuff
}
getStaticValue() {
return "The value of staticValue is " + this.constructor.staticValue;
}
}
class Child1 extends Parent {
constructor() {
super();
//Do child1 stuff
}
}
Child1.staticValue = "Child1";
class Child2 extends Parent {
constructor() {
super();
//Do child2 stuff
}
}
Child2.staticValue = "Child2";
console.log(new Parent().getStaticValue());
console.log(new Child1().getStaticValue());
console.log(new Child2().getStaticValue());
You can pass your static value to the parent constructor using super() in a child class:
class Parent {
constructor(childStaticValue) { // receive the value from the children class
this.staticValue = childStaticValue // and assign it to the local variable
}
getStaticValue() {
return "The value of staticValue is " + this.staticValue;
}
}
class Child1 extends Parent {
constructor() {
super(Child1.staticValue); // pass the value to the parent class
//Do child1 stuff
}
}
Child1.staticValue = "Child1";
class Child2 extends Parent {
constructor() {
super(Child2.staticValue); // pass the value to the parent class
//Do child2 stuff
}
}
Child2.staticValue = "Child2";