Search code examples
javascriptphpclassoopscope-resolution

Javascript equivalent of PHP's :: (Scope Resolution Operator)


In PHP, you can do something like that:

class myClass() {
    function doSomething(someVar) {
         // do something here
    }
    // etc... (other methods and properties)
}

Then, of course, you could call that method after instanciating the class, like that:

$myObj = new myClass();
$myObj->doSomething();

But you would also have the option to call the method as a standalone function, without instantiating the class (but you'd have to pay attention to dependencies in that function), like that:

myClass::doSomething();

I believe it's something borrowed for C++... It's known as a Scope Resolution Operator (Paamayim Nekudotayim in the PHP code...)
http://en.wikipedia.org/wiki/Scope_resolution_operator#PHP
http://www.php.net/manual/en/language.oop5.paamayim-nekudotayim.php

How would you do something like that in JavaScript? It doesn't seem to be possible. Maybe I am approaching this the wrong way, I should disclose what I'm trying to achieve...

I simply have a function, which goes like this:

function submitContactForm(form) {
    // pretty JavaScript...
}

And I'm happy with it being a function. But I'd like to implement a "resetContactForm()" but would like to have it attached somehow to the submitConatctForm function.

I know I could probably do this:

var contactForm = {
   "submit" : function(form) {
       //...
   },
   "reset" : function(form) {
       //...
   }
}

And I'd have answered my own question like that...

But, besides the fact that I don't like this syntax, and would like to avoid it, there is also the fact that the above structure cannot be used as a class definition, it is not the same than in PHP... so going back to the original question: is there a way to have a JavaScript structure that can be used as a class definition and a collection of stand-alone functions at once?


Solution

  • You are mis-understanding prototypal inheritance - you actually can use your second example as a "class" definition and the methods can be invoked either from the "class" or from the "instance":

    // This is a normal JavaScript object
    // not JSON as another commenter pointed out.
    var ContactForm = {
       submit: function(form) {
           form = form || this.form;
           // general contact form submission implementation
       },
       reset: function(form) {
           form = form || this.form;
           // general contact form reset implementation
       },
       setForm: function(form) {
           this.form = form;
       }
    };
    
    // Now we will create an instance of the contactForm "class"
    // We are setting the prototype of `firstContactForm`
    // to point at the `contactForm` object.
    // If we wanted to we could create a function on the
    // ContactForm object (e. g. `create`) that would invoke
    // Object.create for us. (i. e. `ContactForm.create()`)
    var firstContactForm = Object.create(ContactForm);
    firstForm.setForm(document.getElementById("someForm"));
    firstForm.reset();
    
     // But, we can also use the function as a "static":
     ContactForm.reset(document.getElementById("someForm"));
    

    In answer to the other part of your question, if you want to make it something that is invokable "stand-alone" you can also allow the data to be passed in directly, as we are doing in the example with our form = form || this.form; checks in submit and reset.

    Alternately, you can use call and apply (as @elclanrs points out in his answer) and always use this.form:

     ContactForm.reset.call({form: document.getElementById("someForm")});