admin管理员组

文章数量:1302292

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...)

.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?

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/wiki/Scope_resolution_operator#PHP
http://www.php/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?

Share edited Jan 6, 2014 at 18:36 Rolf asked Jan 6, 2014 at 18:31 RolfRolf 5,7535 gold badges44 silver badges63 bronze badges 4
  • 3 That's not JSON syntax, it's JavaScript's object syntax, you don't need the quotes if there aren't any special characters. Paamayim Nekudotayim has no place in JavaScript as there are no classes, no static methods. – elclanrs Commented Jan 6, 2014 at 18:32
  • Well the quotes don't hurt. Thanks anyway. I've removed "JSON" from my post. – Rolf Commented Jan 6, 2014 at 18:34
  • 1 Javascript doesn't have classes so there's no use for the scope resolution operator. Follow the advice in that link for attaching methods to objects in Javascript. Pretty much like @Deepsy just said. – bishop Commented Jan 6, 2014 at 18:35
  • you can only use :: for static functions and constants. You don't just have the option of deciding to use -> or ::, you use -> for functions and constants of instantiated objects, and use :: for static functions and constants of classes. – chiliNUT Commented Jan 6, 2014 at 18:43
Add a ment  | 

4 Answers 4

Reset to default 3

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 menter 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")});

In JavaScript's object syntax you don't need quotes if there aren't any special characters:

var obj = {
   key: function() {
     ...
   },
   ...
}

Paamayim Nekudotayim has no place in JavaScript as there are no classes, no static methods. But JavaScript has a dynamic context, what we call this. It is not in any way similar to this in PHP or other classical inheritance languages, other than the name of the keyword.

A typical JavaScript "class" looks like:

// A "Class"
var Person = (function(){
  // Private stuff, shared across instances
  var instances = [];

  // The constructor AKA "__construct"
  function Person(name) {
    this.name = name;
    instances.push(this); // keep track of instances
  }

  // Static methods, attached to the constructor
  // don't need an instance
  Person.instances = function() {
    return instances;
  };

  // Public methods
  Person.prototype = {
    say: function() {
      return this.name +' says hello!';
    }
  };

  return Person;
}());

Now, how you use this:

var mike = new Person('Mike');
mike.say(); //=> Mike says hello!
Person.instances().length; //=> 1

So good so far. As for "scope resolution" in JavaScript, you can pass the context explicitly; knowing that this is dynamic, you can borrow the Person's say method and invoke it in any other context, for example:

Person.prototype.say.call({name:'John'}); //=> John says hello!

You can make it a class like this:

function ContactForm(form) {
    this.form = form;
}

ContactForm.prototype.submit = function() {
    console.log('submiting: ' + this.form);// do something with the form
}

ContactForm.prototype.reset = function() {
    console.log('reseting: ' + this.form);
}



var someForm = ...;

var form = new ContactForm(someForm);

form.submit();
form.reset();

Or if you want to use them statically you can do as following:

var ContactForm = (function() {
    var reset = function(form) {
        console.log('reseting' + form);
    };

    var submit = function(form) {
        console.log('submiting' + form);
    }

    return {
        submit: submit,
        reset: reset
    }
}()); // note that this is self-executing function

and use it like

ContactForm.submit(form);
ContactForm.reset(form);

Reading Sean Vieira and elclanrs' answers gave me better insight. I've e up with this code as a proof of concept, and to make sure I understood what I was reading. This is essentially a simplified version of elclanrs' answer:

function contactForm(form) {
    this.form = form;
}
contactForm.prototype.submit = function() {
    alert("submit "+this.form);
}
contactForm.prototype.reset = function() {
    alert("reset "+this.form);    
}

// Without instanciating:
contactForm.prototype.submit.call({form:'form2'});

// With instance:
myForm = new contactForm('form1');
myForm.reset();

So it seams this "functionality" is already available in JavaScript, albeit in a different, less straightforward form.

Also, Sean Vieira's approach, pleted:

var ContactForm = {
   submit: function(form) {
       form = form || this.form;
       alert("submit "+form);
   },
   reset: function(form) {
       form = form || this.form;
       alert("reset "+form);
   },
   createForm: function(form) {
       var myForm = Object.create(this);
       myForm.setForm(form);
       return(myForm);
   },
   setForm: function(form) {
       this.form = form;
   }
};

// instanciated
myContactForm = ContactForm.createForm('Me Form');
myContactForm.submit();

// no instance
ContactForm.submit("Some Form");

Also (my contribution), how about using wrapper functions, like that? Looks like a decent option to me.

function contactForm(form) {
    this.form = form;
    this.submit = function() {
        submitContactForm(this.form)
    }
    this.reset = function() {
        resetContactForm(this.form);
    }
}
function submitContactForm(form) {
    alert("submit "+form);
}
function resetContactForm(form) {
    alert("reset "+form);    
}

// Without instanciating:
submitContactForm('form2');

// With instance:
myForm = new contactForm('form1');
myForm.reset();

There is no perfect solution...

本文标签: Javascript equivalent of PHP39s(Scope Resolution Operator)Stack Overflow