tags:

views:

130

answers:

3

Hello everyone!

I need to create simple reusable javascript object publishing several methods and parameterized constructor. After reading through several "OOP in JavaScript" guides I'm sitting here with an empty head. How on the Earth can I do this?

Here my last non-working code:

SomeClass = function(id) {
    this._id = id;
}
(function() {
    function intFun() {
        return this._id;
    }
    SomeClass.prototype.extFun = function() {
        return incFun();
    }
})();
+2  A: 

This is my usual approach:

MyClass = function(x, y, z) {
   // This is the constructor. When you use it with "new MyClass(),"
   // then "this" refers to the new object being constructed. So you can
   // assign member variables to it.
   this.x = x;
   ...
};
MyClass.prototype = {
    doSomething: function() {
        // Here we can use the member variable that
        // we created in the constructor.
        return this.x;
    },
    somethingElse: function(a) {
    }
};

var myObj = new MyClass(1,2,3);
alert(myObj.doSomething()); // this will return the object's "x" member
alert(myObj.x); // this will do the same, by accessing the member directly

Normally the "this" keyword, when used in one of the object's methods, will refer to the object itself. When you use it in the constructor, it will refer to the new object that's being created. So in the above example, both alert statements will display "1".


An exception to this rule is when you pass one of your member functions somewhere else, and then call it. For example,

myDiv.onclick = myObj.doSomething;

In this case, JavaScript ignores the fact that "doSomething" belongs to "myObj". As a result, the "this" inside doSomething will point to another object, so the method won't work as expected. To get around this, you need to specify the object to which "this" should refer. You can do so with JavaScript's "call" function:

myDiv.onclick = function() {
    myObj.doSomething.call(myObj);
}

It's weird, but you'll get used to it eventually. The bottom line is that, when passing around methods, you also need to pass around the object that they should be called on.

JW
This approach couldn't hide internals of the class.
Artem Tikhomirov
JavaScript can't hide internals of the "class".
EndangeredMassa
Yep, bun in can be archived using anonymous function. But I've lost in "this" pointers in example above.
Artem Tikhomirov
By the way, in this example I call object *MyClass* class because of it's role.
Artem Tikhomirov
Artem: You can hide the internals using a trick with closures, but I would get comfortable with the above approach first. I'm editing the post to clarify the use of "this."
JW
Thanks, JW. Very interesting.
Artem Tikhomirov
+1  A: 

I usually don't worry too much about hiding the internals, although I do prefix them with underscores to mark them as not intended to be used outside the "class". Normally what I will do is:

var MyClass = function() {};

MyClass.prototype = {
   _someVar : null,
   _otherVar : null,

   initialize: function( optionHash ) {
                _someVar = optionsHash["varValue"];
                _otherVar = optionsHash["otherValue"];
           },

   method: function( arg ) {
               return _someVar  + arg;  
           },
};

And use it as so...

var myClass = new MyClass( { varValue: -1, otherValue: 10 } );
var foo = myClass.method(6);
tvanfosson
+1  A: 

All vars are private:

SomeClass = function (id) {
    var THIS = this; // unambiguous reference
    THIS._id = id;

    var intFun = function () { // private
        return THIS._id;
    }

    this.extFun = function () { // public
        return intFun();
    }
}

Use THIS within private methods since this won't equal what you might expect.

Jonathan Lonowski
Prefer self over THIS myself.
AnthonyWJones