3

My Question, see below, is how to declare STATIC functions and constants of a pre-ES6 class so they can be inherited?

A recap of the present ES6 class and pre-ES6 classes are given prior to the question so we are all using the same conventions.

In post ES6 we can define a static function in a class as follows:

class MyClass {
    static someMethod () {
        console.log('Doing someMethod');
    }
}

In pre ES6 I can create a base class as follows:

var MyClassBase = function(str){
    this.m_Data = str; // This acts a bit like a constructor where you can assign data within the class
};

You can create an instance pre-ES6 with

var myclassbase = new MyClassBase("Wibble");

You can creat a pre-ES6 non-static member function of that class:

MyClassBase.prototype.EchoData = function(){
    console.log(this.m_Data);
}

You need an instance to call that non-static member function:

var myclassbase = new MyClassBase("Wibble");
myclassbase.EchoData();

To inherit, pre-ES6 I would do something like:

var MyClass = function(str){
    MyClassBase.call(this, str);
};
MyClass.prototype = new MyClassBase(); // inherit

[EDIT]: However @adiga has suggested in the comments (see their useful links) that a better way is:

var MyClass = function(str){
    MyClassBase.call(this, str);
};
MyClass.prototype = Object.create(MyClassBase.prototype);
MyClass.prototype.constructor = MyClass;

That is all background. Now the questions about Statics.

Question: How do I pre-ES6 create static functions in the base class MyClassBase which can be called without an instance, eg:

MyClassBase.StaticFunctionInMyClassBase();
MyClass.StaticFunctionInMyClassBase(); // This could be the inherited function from MyClassBase,
                                        // or may be a redefined overridden function in MyClass

Question: How do I assign static constants to MyClass and MyClassBase pre-ES6 that can be accessed without an instance? For Example,

var result = MyClassBase.TWO_PLUS_TWO; // Echos 4, a predefined static value in MyClassBase
var result = MyClass.TWO_PLUS_TWO; // Echos 5, if TWO_PLUS_TWO has been redefined in MyClass,
                                        // or 4 if TWO_PLUS_TWO has no been redefined in MyClass

Suggestion By Kai: Statics can be included with the following:

var MyClassBase = function(str){
    this.m_Data = str;
};
MyClassBase.STATIC_STRING = "Ooops";

However, when I create my class MyClass which inherits MyClassBase, then MyClass.STATIC_STRING is undefined. I can only access "Ooops" with MyClassBase.STATIC_STRING. Is that normal class conventions?

Rewind
  • 2,554
  • 3
  • 30
  • 56
  • 2
    `MySuperClass.prototype = new MyClass()` is not the correct way to inherit. You need to use `MySuperClass.prototype = Object.create(MyClass.prototype)` and update back the constructor property: `MySuperClass.prototype.constructor = MySuperClass` [JavaScript inheritance: Object.create vs new](https://stackoverflow.com/questions/13040684) – adiga May 22 '21 at 10:41
  • 1
    MyClass.YOURSTATIC = 42. Nothing special. – Kai Lehmann May 22 '21 at 10:42
  • @adiga Thanks for your comment, but I think I have done it right, and it appears to be confirmed by the ticked answer from your link. In my example, if I were to use `Object.create` then my `this.m_Data` would not be available in an instance of `MySuperClass`. By using `MySuperClass.prototype = new MyClass()` means `this.m_Data` will be available in instances of `MySuperClass`. – Rewind May 22 '21 at 11:52
  • `this.m_Data` is already available to instances of `MySuperClass` because of `MyClass.call(this, str)`. – adiga May 22 '21 at 11:54
  • https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Inheritance#setting_teachers_prototype_and_constructor_reference – adiga May 22 '21 at 12:00
  • Please ask a single question per post only. – Bergi May 22 '21 at 13:08
  • @adiga Better references to support your point: https://stackoverflow.com/questions/12592913/what-is-the-reason-to-use-the-new-keyword-here, https://stackoverflow.com/a/17393153/1048572?Benefits-of-using-Object.create-for-inheritance – Bergi May 22 '21 at 13:39
  • @Bergi - I have edited to make it easier to see what the questions are (about Statics) and to add adiga 's better way of implimenting the inheritance. – Rewind May 22 '21 at 16:23
  • For static, you simply add a property to the constructor function: `MyClassBase.StaticFunctionInMyClassBase = (arg) => 'static'` – adiga May 22 '21 at 16:27
  • Thanks @adiga . I can now call `MyClassBase.StaticFunctionInMyClassBase()` without the need of an instance. However, is it normal convention that I should also be able to call `MyClass.StaticFunctionInMyClassBase()`, where the static function is also inherited, because at the moment I cannot appear to do so. – Rewind May 22 '21 at 16:35
  • 1
    "*When I create my class `MyClass` which inherits `MyClassBase`, then `MyClass.STATIC_STRING` is undefined. Is that normal class conventions?*" - yes, this is normal in ES5 inheritance. [To emulate ES6, you would need to manually set the prototype of the constructor](https://stackoverflow.com/q/28674356/1048572) (using `Object.setPrototypeOf`, or its now-deprecated precursor `__proto__`). Notice however that often enough [you want to explicitly refer to `MyBaseClass` anyway](https://stackoverflow.com/a/28648214/1048572). – Bergi May 22 '21 at 16:40
  • Thanks. If @adiga or Bergi put that last comment, `MyClassBase.StaticFunctionInMyClassBase = (arg) => 'static'` and `MyClassBase.STATIC_STRING = "Ooops";` in a brief answer, I will mark this question as answered. Thanks again. – Rewind May 22 '21 at 16:45

1 Answers1

3

How do I create static functions which can be called without an instance, and how do I assign static constants which can be accessed without an instance?

Both methods and constants are just properties of the class (constructor function) object, and are created by assignment:

var MyClassBase = function(str){
    this.m_Data = str;
};
MyClassBase.STATIC_STRING = "Ooops";

See also JavaScript: Class.method vs. Class.prototype.method or Static variables in JavaScript.

When I create my class MyClass which inherits MyClassBase, then MyClass.STATIC_STRING is undefined. Is that normal class conventions?

Yes, this is normal in ES5 inheritance. To emulate ES6, you would need to manually set the prototype of the constructor:

Object.setPrototypeOf(MyClass, MyClassBase);

(or in ES5, one did use the now-deprecated __proto__).

Notice however that often enough you want to explicitly refer to MyBaseClass anyway.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375