Search code examples
javascriptjavascript-objects

Declaring static methods inside of classes declared by functions


Using the function-class method instead of the actual class object, how do I accomplish declaring static methods inside of a class object and access it by that name.

The ultimate goal being single declaration of both things.

Please ignore non standard notation and implicit variables. Code does run as it is inside of a browser console, so it is valid, if not standard. Look at it more like pseudocode.

Section 1: So that this pattern holds

 Be able to use a declared variable name ('Array') as a constructor ('new Array()')

 Be able to use static methods available to same declared variable name ('Array') accessed as an object ('Array.isArray()').

Section 2: Do This

Header: The Obvious Solution

 declare some class name function ('foo')

 As part of created js-object when declaring functions, declare property-method accessing same declared class function name ('foo.isFoo')

 declare instance of class ('foo')

Section 3: Like This

Header: The Goal and Ideal

  declare some class name function ('foo') with intended static method ('isFoo') to be accessed from main class name ('foo.isFoo')

  declare instance of class ('foo')

  try: what throws an error because ('foo.isFoo') isn't a function but ('c.isFoo') is. How do we declare this as a static function?

  catch: just garbage to throw at the end console feed for clarity

instructions

a = "animal";

/*  So that this pattern holds  */
console.log("\nSo that this pattern holds")
b =  new Array(a);
console.log("new Array(a) = [" + b + "]");
console.log("Array.isArray(b) = " + Array.isArray(b));

/*  DO THIS  */
console.log("\nDO THIS");
foo = function (f) {
  this.f = f; 
}
foo.isFoo = c => c instanceof foo;
c = new foo(a);
console.log("new foo(a) = " + c);
console.log("foo.isFoo(c) = " + foo.isFoo(c));

/*  LIKE THIS  */
console.log("\nLIKE THIS");
foo = function (f) {
  this.f = f; 
  this.isFoo = c => c instanceof foo;
}
c = new foo(a);
console.log("new foo(a) = " + c);
try {console.log("foo.isFoo(c) = " + foo.isFoo(c));}
catch {console.log("foo.isFoo is not a function\n     foo.isFoo(c) should = true");}

console output

So that this pattern holds                          debugger eval code:4:9
new Array(a) = [animal]                             debugger eval code:6:9
Array.isArray(b) = true                             debugger eval code:7:9

DO THIS                                             debugger eval code:10:9
new foo(a) = [object Object]                        debugger eval code:16:9
foo.isFoo(c) = true                                 debugger eval code:17:9

LIKE THIS                                           debugger eval code:20:9
new foo(a) = [object Object]                        debugger eval code:26:9
foo.isFoo is not a function
     foo.isFoo(c) should = true

This is meant to be identical in behavior as this

class Point {
    constructor( ...args ) {
        ...do stuff...
    }
    static isPoint( c ) { return c instanceof this; }
}
point = new Point( 3, 7 );
console.log( Point.isPoint( point ) );
console.log( Point.isPoint( Object ) );

Solution

  • Ok, post-edit I understand your question.

    TL;DR No, there is no good way to do what you want.

    In a constructor function this is bound by the new operator to be the newly-created instance, there's no dynamic way to refer to the class itself like there is in a class static method:

    function Foo1 () {
      this; // <- instance
    }
    
    class Foo2 {
      static bar () {
        this; // <- class Foo2
      }
    
      constructor () {
        this; // <- instance
      }
    }
    

    I think based on what you posted in the question you understand all of this so far, and want to replicate the concise static function declaration in the second example.

    You can do this:

    function Foo3 () {
       Foo3.bar = function() {
         this; // <- class Foo3
       }
    }
    

    which seems to do what you want except the bar static method will be redefined every time you call new Foo3. Plus, you still have to refer to the class by name, you can't access it dynamically like you can with this in a class static method.