How to inherit static methods from base class in JavaScript?
Asked Answered
V

7

40

I'm trying to achieve some basic OOP in JavaScript with the prototype way of inheritance. However, I find no way to inherit static members (methods) from the base class.

We can simulate the basic class model by using prototype:

SomeClass = function(){
    var private_members;

    this.public_method = function(){
        //some instance stuff..
    };
};

Class.static_method = function(){
    //some static stuff;
};

//Inheritance
SubClass = function(){ //sub-class definition };
SubClass.prototype = new Class();

However, SubClass doesn't inherit static_method from Class.

Vitkun answered 26/3, 2011 at 9:39 Comment(1)
Mootools is the answer to your problems! :)Unfasten
O
5

Try this:

class BaseClass {
    static baseMethod () {
        console.log("Hello from baseMethod");
    }
}

class MyClass extends BaseClass {
    constructor(props) {
        super(props);
    }
}

Object.assign(MyClass, BaseClass);

They key is Object.assign which should be everyone's new best friend. You can now call any base method from BaseClass using MyClass as follows:

MyClass.baseMethod();

You can see this live and in action on this pen.

Enjoy!

Orthopedist answered 24/6, 2016 at 14:54 Comment(5)
This answer does what I want, the key is the line of code using "Object.assign()"Vitkun
Object.setPrototypeOf(MyClass, BaseClass) will avoid clobbering any overriden static methods.Cecilia
This answer is a strange fit for the question. While it is a viable solution, the question was asked years before the class expression was supported by most browsers and the sample code was clearly using the function prototype for implementing inheritance.Galilee
It works in ES6 without the assignment.Storage
As @Storage mentioned, this answer is wrong. Object.assign isn't needed, you can verify this by running MyClass.baseMethod() without itDiscourage
I
20

In the classical (OO) inheritance pattern, the static methods do not actually get inherited down. Therefore if you have a static method, why not just call: SuperClass.static_method() whenever you need it, no need for JavaScript to keep extra references or copies of the same method.

You can also read this JavaScript Override Patterns to get a better understanding of how to implement inheritance in JavaScript.

Inhumanity answered 29/3, 2011 at 1:20 Comment(0)
P
15

For ES5 you will need to use Object.assign to copy static methods from BaseClass to SubClass but for ES6 it should work without using Object.assign

ES5 Example

var BaseClass = function(){

}

BaseClass.sayHi = function(){
   console.log("Hi!");
}

var SubClass = function(){

}

Object.assign(SubClass , BaseClass);

BaseClass.sayHi();   //Hi
SubClass.sayHi(); //Hi

ES6 Example

class BaseClass {
   static sayHi(){
     console.log("Hi!");
   }
}

class SubClass extends BaseClass{

}

BaseClass.sayHi()   //Hi
SubClass.sayHi() //Hi
Primeval answered 4/2, 2018 at 21:26 Comment(2)
Of course, technically Object.assign is ES6 as well, but you can easily polyfill it or replace it with a loop of assignments.Exospore
It would be better if you provide some transpiled code generated by babel.Nucleoprotein
M
9

After your example code you can do this:

for (var i in Class) {
    SomeClass[i] = Class[i];
}

to copy static members from Class to SubClass.

If you're using jQuery, have a look at the jQuery.Class plugin from JavaScriptMVC. Or you can extend John Resig's Simple JavaScript Inheritance for a more library-agnostic system.

Marilyn answered 12/4, 2011 at 2:21 Comment(1)
I like this answer better because it allows you to customize static methods for some of the children classes OR if you want to have separate static properties for each/some children class.Yingyingkow
O
5

Try this:

class BaseClass {
    static baseMethod () {
        console.log("Hello from baseMethod");
    }
}

class MyClass extends BaseClass {
    constructor(props) {
        super(props);
    }
}

Object.assign(MyClass, BaseClass);

They key is Object.assign which should be everyone's new best friend. You can now call any base method from BaseClass using MyClass as follows:

MyClass.baseMethod();

You can see this live and in action on this pen.

Enjoy!

Orthopedist answered 24/6, 2016 at 14:54 Comment(5)
This answer does what I want, the key is the line of code using "Object.assign()"Vitkun
Object.setPrototypeOf(MyClass, BaseClass) will avoid clobbering any overriden static methods.Cecilia
This answer is a strange fit for the question. While it is a viable solution, the question was asked years before the class expression was supported by most browsers and the sample code was clearly using the function prototype for implementing inheritance.Galilee
It works in ES6 without the assignment.Storage
As @Storage mentioned, this answer is wrong. Object.assign isn't needed, you can verify this by running MyClass.baseMethod() without itDiscourage
S
2

you can access static fields via this.constructor[staticField];

class A {
  static get Foo() { return 'Foo'; }
  
  constructor() {
    console.log(`Class ${this.constructor.name}`, this.constructor.Foo);
  }
}

class B extends A {
    static get Foo() { return 'Baz'; }
}

class C extends A {}

const a = new A();
const b = new B();
const c = new C()
Segalman answered 21/8, 2017 at 21:12 Comment(1)
functions attached to constructors directly are not inherited unless you attach it to Object prototype directly, but then it's visible to all objects not just children of desired class.Chickweed
S
1

How are you implementing 'static' methods? Since JavaScript doesn't have a native class/instance object model, it all depends on how you've designed your own class system.

If you want to be able to inherit anything it'll have to be using the SomeClass.prototype object, rather than putting anything directly on the SomeClass constructor function. So essentially you'll be defining static methods as normal instance methods, but ones that don't care about what value of this is passed into them.

Solorio answered 26/3, 2011 at 10:47 Comment(0)
M
0

Just put the base class constructor as the prototype of the derived class one. This is basically the way ES6 does it behind the scenes

function BaseClass() {
    this.a = 1;
}

BaseClass.prototype.b = function() { /** instance */ };
BaseClass.c = function() { console.log("static ") };

function DerivedClass() {
    BaseClass.call(this); // Super constructor call
}

Object.setPrototypeOf(DerivedClass.prototype, BaseClass.prototype); // Instance inheritance
Object.setPrototypeOf(DerivedClass, BaseClass); // Static inheritance

DerivedClass.c() //→ static

But notice that, at least when I'm writing this, BaseClass does not have Object as its prototype, so it does not inherit static methods like Object.assign(), it instead has Function.prototype as a prototype

class A { }

console.log(Object.getPrototypeOf(A) === Function.prototype); //→ true

This is true unless we explicitly extend Object

class A extends Object { }

console.log(Object.getPrototypeOf(A) === Object); //→ true

console.log(A.assign); //→ function assign() { [native code] }
Merciful answered 30/6, 2023 at 8:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.