js call base class constructor - javascript

Is it possible to call a baseclass constructor from a class?
class BaseCls {
}
class Cls extend BaseCls {
constructor(options){
super(options)
}
}
var instance = new Cls();
Now I want an instance of the baseclas. Something like this:
var baseInstance = new Cls.parent()
I know that I could just call new BaseCls(), but doing it the other way allows me to have only one import.

The superclass is the prototype of the subclass* (which is why superclass static methods are accessible on the subclass), so Object.getPrototypeOf will give you the superclass:
class BaseCls {
constructor() {
console.log("BaseCls");
}
}
class Cls extends BaseCls {
constructor(options){
super(options)
console.log("Cls");
}
}
var base = Object.getPrototypeOf(Cls);
var instance = new base();
You don't have to separate the statements, but if you want to combine them, you have to put () around the call to Object.getPrototypeOf (otherwise new tries to consume it):
var instance = new (Object.getPrototypeOf(Cls))();
And of course, if you wanted to do this generically from a reference to an instance of Cls, it would be:
var superInstance = new (Object.getPrototypeOf(instance.constructor))();
...provided instance doesn't have an own constructor property. Or the rather more convoluted:
var superInstance = new (Object.getPrototypeOf(Object.getPrototypeOf(instance).constructor))();
...if it may have its own constructor property.
* Yes, really. When you use B extends A, there are two parallel lines of inheritance set up: A.prototype is made the prototype of B.prototype, and A is made the prototype of B (whereas in ES5 and earlier, the prototype of a function was always Function.prototype).
Given:
class A {
}
class B extends A {
}
the inheritance looks like this:
B −−−−−−−−−−−−−−> A −−−−−−−−−−−−−−> Function.prototype
B.prototype −−−−> A.prototype −−−−> Object.prototype
class A {
}
class B extends A {
}
console.log(Object.getPrototypeOf(B) === A);
console.log(Object.getPrototypeOf(A) === Function.prototype);
console.log(Object.getPrototypeOf(B.prototype) === A.prototype);
console.log(Object.getPrototypeOf(A.prototype) === Object.prototype);

Related

How can some methods be in the prototype but not be passed around via Object.assign, while some others are

Take the following classes A, B and C and their instances a, b and c
class A {
constructor() {
this.method1 = function() {}
}
method2() {}
}
A.prototype.method3 = function() {};
class B extends A {
constructor() {
super();
}
}
class C {
constructor() {}
}
Object.assign(C.prototype, A.prototype);
const a = new A();
const b = new B();
const c = new C();
How come class B inherits method 2 but class C doesn't?
How can the following statements be both true ?
A.prototype.method2 !== undefined
c.method2 === undefined
In case you are wondering, c.method3 !== undefined, so there is some fundamental difference between the two that I cannot grasp.
You can fiddle around with it here https://jsfiddle.net/pdn64bv2/
Update
I thought it would be useful to share how to achieve the effect I was expecting Object.assign(C.prototype, A.prototype) to produce.
Object.getOwnPropertyNames(A.prototype).forEach(name => {
if (name !== "constructor") C.prototype[name] = A.prototype[name];
});
This copies the prototype of A to C, including non-enumerable properties.
Note that it does not copy the hole prototype chain the way Reflect.setPrototypeOf(C.prototype, A.prototype) would, which may be interesting for object composition.
There are two things conspiring to have this effect:
1) Object.assign will only copy the enumerable own properties of an object. Any non-enumerable properties will not be copied
2) When you use the class keyword, any methods you define are not enumerable. This is different from when you assign something to an object with A.prototype.method3 = function() {}, where the property will be enumerable.
So since A.prototype.method2 is not enumerable, it does not get put onto C.prototype when you do Object.assign(C.prototype, A.prototype);
Another way to see that class methods aren't enumerable is to use Object.keys. The ones defined with the class keyword are not there:
class A {
constructor() {
this.method1 = function() {}
}
method2() {}
}
A.prototype.method3 = function() {};
console.log(Object.keys(A.prototype));
console.log(A.prototype.method2); // it's there
console.log(Object.prototype.propertyIsEnumerable('method2')); // but it's not enumerable

Javascript prototype inheritance over multiple prototypes

i've got some problems with javascript prototype inheritance when this inheritance is stretched between multiple objects: surely i'm doing something wrong but for the moment i'm failing to understand what.
The whole Prototype's inheritance system seems to lose available methods when extending a prototype that already extends a prototype.
An example:
consider the following Objects
object A
prototype with extended function ab
prototype with extended function cd
object B
extends A
object C
extends B
prototype with extended function ef
object D
extends C
here an example of these Objects, as i have defined them:
Object A
function A () {
this.someproperty = someValue;
}
A.prototype.ab = function () {
// does something
}
A.prototype.cd = function () {
// does something
}
Object B
function B () {
A.call(this);
this.someOtherProperty = someValue;
}
B.prototype = A.prototype;
B.prototype.constructor = B;
Object C
function C () {
B.call(this);
}
C.prototype = B.prototype;
C.prototype.constructor = C;
C.prototype.ef = function () {
// does something
}
Object D
function D () {
C.call(this);
this.someOtherProperty = someValue;
}
D.prototype = C.prototype;
D.prototype.constructor = D;
given the example above, i am expecting that initializing a variable as "new D", such variable should have available the methods ab, cd, and ef, accessible with
variable.ab()
variable.cd()
variable.ef()
It seems instead that all of these are undefined.
Please consider that if i initialize "new B" instead:
variable.ab()
variable.cd()
are defined and working
am i doing something wrong or prototype inheritance cannot be over stretched over multiple objects?
Thank you!
B.prototype = A.prototype;
It's not inheritance, it's overwriting: A.prototype and B.prototype become the same object. It should be
B.prototype = Object.create(A.prototype);
Here is your code re-written with ES6 classes. #mbojko's answer is quite correct (so please accept that one rather than this as #mbojko is directly answering your question), however if you are going to use deep levels of class inheritance of this kind (and many would argue that you shouldn't - I tend to feel for some problems it is the right approach but you certainly need to be cautious) I would suggest using ES6 classes instead - clearer syntax and more guards against incorrect usage.
class A{
constructor (){
this.someproperty = 0;
}
ab(){
//...
return "called ab method"
}
cd(){
//...
}
}
class B extends A{
constructor(){
super();
this.someOtherProperty = 1;
}
}
class C extends B{
ef(){
//...
}
}
class D extends C{
constructor(){
super();
this.someOtherProperty = 2;
}
}
const d=new D();
console.log(d.ab());

ES6: Why do extending classes need to explicitly call super? [duplicate]

Is it possible to extend a class in ES6 without calling the super method to invoke the parent class?
EDIT: The question might be misleading. Is it the standard that we have to call super() or am I missing something?
For example:
class Character {
constructor(){
console.log('invoke character');
}
}
class Hero extends Character{
constructor(){
super(); // exception thrown here when not called
console.log('invoke hero');
}
}
var hero = new Hero();
When I'm not calling super() on the derived class I'm getting a scope problem -> this is not defined
I'm running this with iojs --harmony in v2.3.0
The rules for ES2015 (ES6) classes basically come down to:
In a child class constructor, this cannot be used until super is called.
ES6 class constructors MUST call super if they are subclasses, or they must explicitly return some object to take the place of the one that was not initialized.
This comes down to two important sections of the ES2015 spec.
Section 8.1.1.3.4 defines the logic to decide what this is in the function. The important part for classes is that it is possible for this be in an "uninitialized" state, and when in this state, attempting to use this will throw an exception.
Section 9.2.2, [[Construct]], which defines the behavior of functions called via new or super. When calling a base class constructor, this is initialized at step #8 of [[Construct]], but for all other cases, this is uninitialized. At the end of construction, GetThisBinding is called, so if super has not been called yet (thus initializing this), or an explicit replacement object was not returned, the final line of the constructor call will throw an exception.
The new ES6 class syntax is only an other notation for "old" ES5 "classes" with prototypes. Therefore you cannot instantiate a specific class without setting its prototype (the base class).
Thats like putting cheese on your sandwich without making it. Also you cannot put cheese before making the sandwich, so...
...using this keyword before calling the super class with super() is not allowed, too.
// valid: Add cheese after making the sandwich
class CheeseSandwich extend Sandwich {
constructor() {
super();
this.supplement = "Cheese";
}
}
// invalid: Add cheese before making sandwich
class CheeseSandwich extend Sandwich {
constructor() {
this.supplement = "Cheese";
super();
}
}
// invalid: Add cheese without making sandwich
class CheeseSandwich extend Sandwich {
constructor() {
this.supplement = "Cheese";
}
}
If you don’t specify a constructor for a base class, the following definition is used:
constructor() {}
For derived classes, the following default constructor is used:
constructor(...args) {
super(...args);
}
EDIT: Found this on developer.mozilla.org:
When used in a constructor, the super keyword appears alone and must be used before the this keyword can be used.
Source
There have been multiple answers and comments stating that super MUST be the first line inside constructor. That is simply wrong. #loganfsmyth answer has the required references of the requirements, but it boil down to:
Inheriting (extends) constructor must call super before using this and before returning even if this isn't used
See fragment below (works in Chrome...) to see why it might make sense to have statements (without using this) before calling super.
'use strict';
var id = 1;
function idgen() {
return 'ID:' + id++;
}
class Base {
constructor(id) {
this.id = id;
}
toString() { return JSON.stringify(this); }
}
class Derived1 extends Base {
constructor() {
var anID = idgen() + ':Derived1';
super(anID);
this.derivedProp = this.baseProp * 2;
}
}
alert(new Derived1());
You can omit super() in your subclass, if you omit the constructor altogether in your subclass. A 'hidden' default constructor will be included automatically in your subclass. However, if you do include the constructor in your subclass, super() must be called in that constructor.
class A{
constructor(){
this.name = 'hello';
}
}
class B extends A{
constructor(){
// console.log(this.name); // ReferenceError
super();
console.log(this.name);
}
}
class C extends B{} // see? no super(). no constructor()
var x = new B; // hello
var y = new C; // hello
Read this for more information.
The answer by justyourimage is the easiest way, but his example is a little bloated. Here's the generic version:
class Base {
constructor(){
return this._constructor(...arguments);
}
_constructor(){
// just use this as the constructor, no super() restrictions
}
}
class Ext extends Base {
_constructor(){ // _constructor is automatically called, like the real constructor
this.is = "easy"; // no need to call super();
}
}
Don't extend the real constructor(), just use the fake _constructor() for the instantiation logic.
Note, this solution makes debugging annoying because you have to step into an extra method for every instantiation.
Just registered to post this solution since the answers here don't satisfy me the least since there is actually a simple way around this. Adjust your class-creation pattern to overwrite your logic in a sub-method while using only the super constructor and forward the constructors arguments to it.
As in you do not create an constructor in your subclasses per se but only reference to an method that is overridden in the respective subclass.
That means you set yourself free from the constructor functionality enforced upon you and refrain to a regular method - that can be overridden and doesn't enforce super() upon you letting yourself the choice if, where and how you want to call super (fully optional) e.g.:
super.ObjectConstructor(...)
class Observable {
constructor() {
return this.ObjectConstructor(arguments);
}
ObjectConstructor(defaultValue, options) {
this.obj = { type: "Observable" };
console.log("Observable ObjectConstructor called with arguments: ", arguments);
console.log("obj is:", this.obj);
return this.obj;
}
}
class ArrayObservable extends Observable {
ObjectConstructor(defaultValue, options, someMoreOptions) {
this.obj = { type: "ArrayObservable" };
console.log("ArrayObservable ObjectConstructor called with arguments: ", arguments);
console.log("obj is:", this.obj);
return this.obj;
}
}
class DomainObservable extends ArrayObservable {
ObjectConstructor(defaultValue, domainName, options, dependent1, dependent2) {
this.obj = super.ObjectConstructor(defaultValue, options);
console.log("DomainObservable ObjectConstructor called with arguments: ", arguments);
console.log("obj is:", this.obj);
return this.obj;
}
}
var myBasicObservable = new Observable("Basic Value", "Basic Options");
var myArrayObservable = new ArrayObservable("Array Value", "Array Options", "Some More Array Options");
var myDomainObservable = new DomainObservable("Domain Value", "Domain Name", "Domain Options", "Dependency A", "Depenency B");
cheers!
#Bergi mentioned new.target.prototype, but I was looking for a concrete example proving that you can access this (or better, the reference to the object the client code is creating with new, see below) without having to call super() at all.
Talk is cheap, show me the code... So here is an example:
class A { // Parent
constructor() {
this.a = 123;
}
parentMethod() {
console.log("parentMethod()");
}
}
class B extends A { // Child
constructor() {
var obj = Object.create(new.target.prototype)
// You can interact with obj, which is effectively your `this` here, before returning
// it to the caller.
return obj;
}
childMethod(obj) {
console.log('childMethod()');
console.log('this === obj ?', this === obj)
console.log('obj instanceof A ?', obj instanceof A);
console.log('obj instanceof B ?', obj instanceof B);
}
}
b = new B()
b.parentMethod()
b.childMethod(b)
Which will output:
parentMethod()
childMethod()
this === obj ? true
obj instanceof A ? true
obj instanceof B ? true
So you can see that we are effectively creating an object of type B (the child class) which is also an object of type A (its parent class) and within the childMethod() of child B we have this pointing to the object obj which we created in B's constructor with Object.create(new.target.prototype).
And all this without caring about super at all.
This leverages the fact that in JS a constructor can return a completely different object when the client code constructs a new instance with new.
Hope this helps someone.
Try:
class Character {
constructor(){
if(Object.getPrototypeOf(this) === Character.prototype){
console.log('invoke character');
}
}
}
class Hero extends Character{
constructor(){
super(); // throws exception when not called
console.log('invoke hero');
}
}
var hero = new Hero();
console.log('now let\'s invoke Character');
var char = new Character();
Demo
I would recommend to use OODK-JS if you intend to develop following OOP concepts.
OODK(function($, _){
var Character = $.class(function ($, µ, _){
$.public(function __initialize(){
$.log('invoke character');
});
});
var Hero = $.extends(Character).class(function ($, µ, _){
$.public(function __initialize(){
$.super.__initialize();
$.log('invoke hero');
});
});
var hero = $.new(Hero);
});
Simple solution: I think its clear no need for explanation.
class ParentClass() {
constructor(skipConstructor = false) { // default value is false
if(skipConstructor) return;
// code here only gets executed when 'super()' is called with false
}
}
class SubClass extends ParentClass {
constructor() {
super(true) // true for skipping ParentClass's constructor.
// code
}
}

Is it possible in javascript to inherit properties from another class - rather than an existing object?

For example in PHP if you wanted a class to inherit properties of another class you would reference the parent class
<?php
class BaseController {
// ....
}
class UserController extends BaseController {
// ....
}
However in javascript if you want a new class or object to inherit some properties from another class - it seems you need to assign an - already instantiated - object of the class you want to inherit from to your objects prototype.
e.g. If you want to create a brand new object and access the properties of an existing object:
var robot = {
active : "yes",
primeDirective : function() {
console.log("Must kill all humans!");
}
};
var bender = Object.create(robot);
bender.primeDirective(); => "Must kill all humans!"
or if you have an existing object, you can assign the existing object to prototype using __proto__
var robot = {
active : "yes",
primeDirective : function() {
console.log("Do a flip!");
}
};
var bender = {
name : "Bender Bending Rodriguez"
};
bender.__proto__ = robot;
bender.primeDirective(); => "Do a flip!"
both these methods require an already created object to inherit properties from, is it possible for a class definition to inherit from another class - similar to the extends functionality in PHP?
In ES5 JavaScript the correct way to derive a class is to use Object.create passing the base class's prototype, not an instance, and then to ensure that all functions are part of that prototype.
// a properly formed constructor function
function Robot(name) {
this.name = name;
}
// all functions belong on the prototype
Robot.prototype.primeDirective = function() {
...
}
// create derived class
function BendingUnit22(name) {
Robot.call(this, name); // invoke superclass constructor
}
// create and attach a new prototype object chained from the base class
BendingUnit22.prototype = Object.create(Robot.prototype);
// and re-attach the constructor
BendingUnit22.prototype.constructor = BendingUnit22;
// add new or overriding functions here
BendingUnit22.prototype.primeDirective = function() {
...
}
var bender = new BendingUnit22("Bender Bending Rodriguez");
You'll need to create a constructor (or an ES6 class) if you want to inherit a little less dynamically.
function Robot() {
this.active = true;
}
Robot.prototype.primeDirective = function() {
console.log("Must kill all humans!");
};
var bender = new Robot(); // Yey!
To create a new inheriting constructor:
function HumanoidRobot() {
Robot.apply(this, arguments);
this.legs = 2;
}
HumanoidRobot.prototype = Object.create(Robot.prototype);
HumanoidRobot.prototype.constructor = HumanoidRobot;
This process becomes a lot easier with ES6 classes, which hide all this ugliness from you!
class Robot {
constructor() {
this.active = true;
}
primeDirective() {
console.log("Must kill all humans!");
}
}
class HumanoidRobot extends Robot() {
constructor() {
super()
this.legs = 2;
}
}
No, there is no built in mode for extending classes in Javascript, because it is not a class based but prototype based language.
However, there are many frameworks that implement the 'extend' behaviour, for example in Prototype:
var robot = Class.extend({ ... });
var bender = robot.extend({ ... });
http://ejohn.org/blog/simple-javascript-inheritance/
But many other frameworks support the same, for example Underscore _.extend()
http://underscorejs.org/#extend
There are 3 kind of inheritance possible in JavaScript.
Pseudo Classical (Like the one you are looking for)
/**
* Create a new constructor function, whose prototype is the parent object's prototype.
* Set the child's prototype to the newly created constructor function.
**/
var extendObj = function (childObj, parentObj) {
var tmpObj = function () {}
tmpObj.prototype = parentObj.prototype;
childObj.prototype = new tmpObj();
childObj.prototype.constructor = childObj;
};
(https://jsfiddle.net/nikdtu/4wzuwhqw/)
Functional
(https://jsfiddle.net/nikdtu/eh7u4pxd/)
Prototypal (Object.create)
(https://jsfiddle.net/nikdtu/dnjkx8w1/)
Luckily I documented that during a project and captured those JSfiddles.
I hope You will find the required help from these.
I think this is what you are looking for
// define the Person Class
function Person() {}
Person.prototype.walk = function(){
alert ('I am walking!');
};
Person.prototype.sayHello = function(){
alert ('hello');
};
// define the Student class
function Student() {
// Call the parent constructor
Person.call(this);
}
// inherit Person
Student.prototype = new Person();
// correct the constructor pointer because it points to Person
Student.prototype.constructor = Student;
// replace the sayHello method
Student.prototype.sayHello = function(){
alert('hi, I am a student');
}
// add sayGoodBye method
Student.prototype.sayGoodBye = function(){
alert('goodBye');
}
var student1 = new Student();
student1.sayHello();
student1.walk();
student1.sayGoodBye();
// check inheritance
alert(student1 instanceof Person); // true
alert(student1 instanceof Student); // true

How to extend a class without having to use super in ES6?

Is it possible to extend a class in ES6 without calling the super method to invoke the parent class?
EDIT: The question might be misleading. Is it the standard that we have to call super() or am I missing something?
For example:
class Character {
constructor(){
console.log('invoke character');
}
}
class Hero extends Character{
constructor(){
super(); // exception thrown here when not called
console.log('invoke hero');
}
}
var hero = new Hero();
When I'm not calling super() on the derived class I'm getting a scope problem -> this is not defined
I'm running this with iojs --harmony in v2.3.0
The rules for ES2015 (ES6) classes basically come down to:
In a child class constructor, this cannot be used until super is called.
ES6 class constructors MUST call super if they are subclasses, or they must explicitly return some object to take the place of the one that was not initialized.
This comes down to two important sections of the ES2015 spec.
Section 8.1.1.3.4 defines the logic to decide what this is in the function. The important part for classes is that it is possible for this be in an "uninitialized" state, and when in this state, attempting to use this will throw an exception.
Section 9.2.2, [[Construct]], which defines the behavior of functions called via new or super. When calling a base class constructor, this is initialized at step #8 of [[Construct]], but for all other cases, this is uninitialized. At the end of construction, GetThisBinding is called, so if super has not been called yet (thus initializing this), or an explicit replacement object was not returned, the final line of the constructor call will throw an exception.
The new ES6 class syntax is only an other notation for "old" ES5 "classes" with prototypes. Therefore you cannot instantiate a specific class without setting its prototype (the base class).
Thats like putting cheese on your sandwich without making it. Also you cannot put cheese before making the sandwich, so...
...using this keyword before calling the super class with super() is not allowed, too.
// valid: Add cheese after making the sandwich
class CheeseSandwich extend Sandwich {
constructor() {
super();
this.supplement = "Cheese";
}
}
// invalid: Add cheese before making sandwich
class CheeseSandwich extend Sandwich {
constructor() {
this.supplement = "Cheese";
super();
}
}
// invalid: Add cheese without making sandwich
class CheeseSandwich extend Sandwich {
constructor() {
this.supplement = "Cheese";
}
}
If you don’t specify a constructor for a base class, the following definition is used:
constructor() {}
For derived classes, the following default constructor is used:
constructor(...args) {
super(...args);
}
EDIT: Found this on developer.mozilla.org:
When used in a constructor, the super keyword appears alone and must be used before the this keyword can be used.
Source
There have been multiple answers and comments stating that super MUST be the first line inside constructor. That is simply wrong. #loganfsmyth answer has the required references of the requirements, but it boil down to:
Inheriting (extends) constructor must call super before using this and before returning even if this isn't used
See fragment below (works in Chrome...) to see why it might make sense to have statements (without using this) before calling super.
'use strict';
var id = 1;
function idgen() {
return 'ID:' + id++;
}
class Base {
constructor(id) {
this.id = id;
}
toString() { return JSON.stringify(this); }
}
class Derived1 extends Base {
constructor() {
var anID = idgen() + ':Derived1';
super(anID);
this.derivedProp = this.baseProp * 2;
}
}
alert(new Derived1());
You can omit super() in your subclass, if you omit the constructor altogether in your subclass. A 'hidden' default constructor will be included automatically in your subclass. However, if you do include the constructor in your subclass, super() must be called in that constructor.
class A{
constructor(){
this.name = 'hello';
}
}
class B extends A{
constructor(){
// console.log(this.name); // ReferenceError
super();
console.log(this.name);
}
}
class C extends B{} // see? no super(). no constructor()
var x = new B; // hello
var y = new C; // hello
Read this for more information.
The answer by justyourimage is the easiest way, but his example is a little bloated. Here's the generic version:
class Base {
constructor(){
return this._constructor(...arguments);
}
_constructor(){
// just use this as the constructor, no super() restrictions
}
}
class Ext extends Base {
_constructor(){ // _constructor is automatically called, like the real constructor
this.is = "easy"; // no need to call super();
}
}
Don't extend the real constructor(), just use the fake _constructor() for the instantiation logic.
Note, this solution makes debugging annoying because you have to step into an extra method for every instantiation.
Just registered to post this solution since the answers here don't satisfy me the least since there is actually a simple way around this. Adjust your class-creation pattern to overwrite your logic in a sub-method while using only the super constructor and forward the constructors arguments to it.
As in you do not create an constructor in your subclasses per se but only reference to an method that is overridden in the respective subclass.
That means you set yourself free from the constructor functionality enforced upon you and refrain to a regular method - that can be overridden and doesn't enforce super() upon you letting yourself the choice if, where and how you want to call super (fully optional) e.g.:
super.ObjectConstructor(...)
class Observable {
constructor() {
return this.ObjectConstructor(arguments);
}
ObjectConstructor(defaultValue, options) {
this.obj = { type: "Observable" };
console.log("Observable ObjectConstructor called with arguments: ", arguments);
console.log("obj is:", this.obj);
return this.obj;
}
}
class ArrayObservable extends Observable {
ObjectConstructor(defaultValue, options, someMoreOptions) {
this.obj = { type: "ArrayObservable" };
console.log("ArrayObservable ObjectConstructor called with arguments: ", arguments);
console.log("obj is:", this.obj);
return this.obj;
}
}
class DomainObservable extends ArrayObservable {
ObjectConstructor(defaultValue, domainName, options, dependent1, dependent2) {
this.obj = super.ObjectConstructor(defaultValue, options);
console.log("DomainObservable ObjectConstructor called with arguments: ", arguments);
console.log("obj is:", this.obj);
return this.obj;
}
}
var myBasicObservable = new Observable("Basic Value", "Basic Options");
var myArrayObservable = new ArrayObservable("Array Value", "Array Options", "Some More Array Options");
var myDomainObservable = new DomainObservable("Domain Value", "Domain Name", "Domain Options", "Dependency A", "Depenency B");
cheers!
#Bergi mentioned new.target.prototype, but I was looking for a concrete example proving that you can access this (or better, the reference to the object the client code is creating with new, see below) without having to call super() at all.
Talk is cheap, show me the code... So here is an example:
class A { // Parent
constructor() {
this.a = 123;
}
parentMethod() {
console.log("parentMethod()");
}
}
class B extends A { // Child
constructor() {
var obj = Object.create(new.target.prototype)
// You can interact with obj, which is effectively your `this` here, before returning
// it to the caller.
return obj;
}
childMethod(obj) {
console.log('childMethod()');
console.log('this === obj ?', this === obj)
console.log('obj instanceof A ?', obj instanceof A);
console.log('obj instanceof B ?', obj instanceof B);
}
}
b = new B()
b.parentMethod()
b.childMethod(b)
Which will output:
parentMethod()
childMethod()
this === obj ? true
obj instanceof A ? true
obj instanceof B ? true
So you can see that we are effectively creating an object of type B (the child class) which is also an object of type A (its parent class) and within the childMethod() of child B we have this pointing to the object obj which we created in B's constructor with Object.create(new.target.prototype).
And all this without caring about super at all.
This leverages the fact that in JS a constructor can return a completely different object when the client code constructs a new instance with new.
Hope this helps someone.
Try:
class Character {
constructor(){
if(Object.getPrototypeOf(this) === Character.prototype){
console.log('invoke character');
}
}
}
class Hero extends Character{
constructor(){
super(); // throws exception when not called
console.log('invoke hero');
}
}
var hero = new Hero();
console.log('now let\'s invoke Character');
var char = new Character();
Demo
I would recommend to use OODK-JS if you intend to develop following OOP concepts.
OODK(function($, _){
var Character = $.class(function ($, µ, _){
$.public(function __initialize(){
$.log('invoke character');
});
});
var Hero = $.extends(Character).class(function ($, µ, _){
$.public(function __initialize(){
$.super.__initialize();
$.log('invoke hero');
});
});
var hero = $.new(Hero);
});
Simple solution: I think its clear no need for explanation.
class ParentClass() {
constructor(skipConstructor = false) { // default value is false
if(skipConstructor) return;
// code here only gets executed when 'super()' is called with false
}
}
class SubClass extends ParentClass {
constructor() {
super(true) // true for skipping ParentClass's constructor.
// code
}
}

Categories

Resources