0

How to enable the use of static methods while preventing the use of instance functions without using the new operator? In the example below, the constructor will throw an exception if you try to invoke it without the new operator. Unfortunately, this also prevents access to genuine static functions in the prototype, that are perfectly ok to invoke without constructing an object first:

    function TestIt() {

            if(this.constructor == arguments.callee && !this._constructed ) 
                    this._constructed = true;
            else 
                    throw "this function must be called with the new operator";

    }

    TestIt.prototype.someStaticMethod=function() {
            console.log('hello');
    }

    TestIt.prototype.someStaticMethod(); //ok

    var t=new TestIt();
    t.someStaticMethod(); //ok

    TestIt.someStaticMethod(); //exception raised

Is there a way to get TestIt.someStaticMethod() to work in this context anyway? Why does TestIt.someStaticMethod() actually call the constructor in the first place? It is a bit counterintuitive that it does so.

erik
  • 31
  • 1
  • 4
  • *"Why does TestIt.someStaticMethod() actually call the constructor in the first place?"* It doesn't. I'm pretty sure you get an error like "undefined is not a function". That's because TestIt doesn't have a property someStaticMethod. That has nothing to do with what happens inside TestIt. – Felix Kling Aug 27 '14 at 13:18

1 Answers1

1

A simpler way to test if the constructor was called without new is this:

function TestIt() {
  if (!(this instanceof TestIt)) {
    throw "this function must be called with the new operator";
  }
}

As for the static methods, you should perhaps define them on the class (constructor) instead of on the prototype. Properties defined on the prototype are accessible to instances, while static methods should be accessible on the class itself.

TestIt.someStaticMethod = function() {
  console.log('hello');
}

var t=new TestIt();
t.someStaticMethod(); // no method here, exception

TestIt.someStaticMethod(); // works
Tibos
  • 27,507
  • 4
  • 50
  • 64
  • You are right. It solves the problem! So simple. Concerning `!(this instanceof TestIt)`, I did not see it recommended in [SO question](http://stackoverflow.com/questions/367768/how-to-detect-if-a-function-is-called-as-constructor) where they recommended the other construct. Were the answers incomplete/wrong there? The top answer even got a rating of 50 ... – erik Aug 26 '14 at 13:34
  • @user1471399 The problem in that question was that the same function was used to construct an object and assigned as a method on that object. I find such edge cases to never be useful in practice. – Tibos Feb 02 '15 at 05:59