How to inherit from a class in javascript?
I have changed how I do this now, I try to avoid using constructor functions and their prototype
property, but my old answer from 2010 is still at the bottom. I now prefer Object.create()
. Object.create
is available in all modern browsers.
I should note that Object.create
is usually much slower than using new
with a function constructor.
//The prototype is just an object when you use `Object.create()`
var Base = {};
//This is how you create an instance:
var baseInstance = Object.create(Base);
//If you want to inherit from "Base":
var subInstance = Object.create(Object.create(Base));
//Detect if subInstance is an instance of Base:
console.log(Base.isPrototypeOf(subInstance)); //True
jsfiddle
One of the big benefits of using Object.create is being able to pass in a defineProperties argument, which gives you significant control over how properties on the class can be accessed and enumerated over, and I also use functions to create instances, these serve as constructors in a way, as you can do initialization at the end instead of just returning the instance.
var Base = {};
function createBase() {
return Object.create(Base, {
doSomething: {
value: function () {
console.log("Doing something");
},
},
});
}
var Sub = createBase();
function createSub() {
return Object.create(Sub, {
doSomethingElse: {
value: function () {
console.log("Doing something else");
},
},
});
}
var subInstance = createSub();
subInstance.doSomething(); //Logs "Doing something"
subInstance.doSomethingElse(); //Logs "Doing something else"
console.log(Base.isPrototypeOf(subInstance)); //Logs "true"
console.log(Sub.isPrototypeOf(subInstance)); //Logs "true
jsfiddle
This is my original answer from 2010:
function Base ( ) {
this.color = "blue";
}
function Sub ( ) {
}
Sub.prototype = new Base( );
Sub.prototype.showColor = function ( ) {
console.log( this.color );
}
var instance = new Sub ( );
instance.showColor( ); //"blue"
how can I inherit a js class from another js class which are separate files?
You probably want to take advantage of JavaScript modules.
// Shape.js
export default class Shape {
constructor() {
}
// ...
}
Then in a separate file:
// Circle.js
import Shape from "./Shape.js"
export default class Circle extends Shape {
constructor() {
super()
}
// ...
}
The real annoyance is that the import
reference is always relative to the current file. If you're using Webpack to transpile and/or bundle your module, you can take advantage of their resolve option.
ES6 Class Multiple inheritance
An object can only have one prototype. Inheriting from two classes can be done by creating a parent object as a combination of two parent prototypes.
The syntax for subclassing makes it possible to do that in the declaration, since the right-hand side of the extends
clause can be any expression. Thus, you can write a function that combines prototypes according to whatever criteria you like, and call that function in the class declaration.
Class constructor inheritance using `extends` with passed in arguments
The parent
and child
are class objects and they dont have relation each other. From your code, when you call let child = new Child()
, you did nothing with the x
, y
, w
and h
in your Child
constructor.
The Classes are templates, the inheritance means you copy the parent's methods implementation.
You can just think the Parent
and Child
classes are different each other - just the Child
class has all the methods that the Parent
has.
When you inherit a class, you need to pass the parameters that the Parent
class needs in its constructor.
You can fix it like below:
class Parent {
constructor(x, y, w, h) {
this.x = x; //if I put values directly here it works
this.y = y;
this.w = w;
this.h = h;
}
}
class Child extends Parent {
constructor(x, y, w, h) {
super(x, y, w, h); // <- Passing the parameters
this.pt1 = {x: this.x, y: this.y};
this.pt2 = {x: this.x + this.w, y: this.y};
this.pt3 = {x: this.x + this.w, y: this.y + this.h};
this.pt4 = {x: this.x, y: this.y + this.h};
}
}
let parent = new Parent(300, 50, 50, 200);
let child = new Child(300, 50, 50, 200); // <- pass the values
console.log(child.pt1)
console.log(child.pt3)
Inheritance and Super in JavaScript
What is the constructor and super() keyword. I believe it is for inheritance?
That's right. The above sets up class B
and then has class A
subclass it. The constructor
is the function called when you create a new instance of the class, as in the let c = new A("Testing", "37");
line in the code. Unlike some other languages, in JavaScript there can only be one constructor for a class.
super
is used in subclasses to refer to the superclass. In a constructor, you call super
as though it were a function, and that calls the superclass's constructor function, giving it a chance to do its initialization of the new object that was created by new
. So for instance, in A
's constructor
, super()
calls B
's constructor
.
You can also use super
as the source of a property accessor expression to access properties (including methods) on the superclass. That's what's happening in A
's printName
method, where it uses super.printName()
to call B
's printName
method. (Which will fail, because B
doesn't have a printName
method; B
's method is called printn
.)
I'd be remiss if I didn't point out that although this looks a lot like the class-based OOP in, say, Java or C#, it isn't. It's syntactic sugar (the good kind of sugar) for setting up JavaScript's normal prototypical inheritance using constructor functions. It hugely simplifies setting up prototypical inheritance hierarchies using constructor functions. I'd also be remiss if I didn't point out that using constructor functions to do prototypical inheritance is not necessary, you can do prototypical inheritance without using constructor functions via Object.create
.
There's a lot more to explore. MDN is probably a good starting point.
I can't get this code to work.
The C
in Console.log
shouldn't be capitalized, so change
Console.log(c.printn());
to
console.log(c.printn());
Other than that, if you're using a JavaScript engine that supports class
(such as the one in Google Chrome or Mozilla Firefox), that code works fine although note again that A
seems to expect B
to have a printName
method, but it doesn't, and the code at the end is calling printn
which only B
has (which is fine, it just means A
's code isn't really involved).
class B { constructor(name) { this.name = name; }
printn() { return this.name; }}
class A extends B { constructor(name, age) { super(name); this._age = age; }
get age() { return this._age; }
printName(){ return super.printName(); }}
let c = new A("Testing", "37");console.log(c.printn());
Is it possible in javascript to inherit properties from another class - rather than an existing object?
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");
Can a child class overwrite a private field inherited from a superclass?
JavaScript does not support directly accessing private properties inherited from another class, which is how private members are supposed to work. You seem to want the functionality of protected properties. As of 2022, JavaScript does not support protected properties or members of any kind. Why that is, I can't imagine, since other OOP languages have allowed said functionality since time immemorial.
If you have control over the code of the parent class, you can simulate protected properties by using symbols.
const className = Symbol();
class Parent {
[className] = 'Parent'; // create protected [className]
getClassName() {
return this[className]; // return [className] from object
}
}
class Child extends Parent {
[className] = 'Child'; // re-define [className] for this child class
}
console.log(new Child().getClassName()); // --> this prints 'Child'
Related Topics
How to Detect Escape Key Press with Pure Js or Jquery
Copy/Put Text on the Clipboard with Firefox, Safari and Chrome
How to Make Cross Domain Request
What Is "Function*" in JavaScript
How to Add Bootstrap in Angular 6 Project
How to Get a Value of a <Span> Using Jquery
How to Use Google.Maps.Event.Trigger(Map, 'Resize')
Doing Links Like Twitter, Hash-Bang #! Url'S
Saving and Loading an Image from Localstorage
Bootstrap Modal: Is Not a Function
Getelementsbyclassname() with Two Classes
Possible to Associate Label with Checkbox Without Using "For=Id"
How to Make Recaptcha a Required Field
Get List of All Input Objects Using JavaScript, Without Accessing a Form Object
Img-Src' Was Not Explicitly Set, So 'Default-Src' Is Used as a Fallback