Ok, speaking of reading over things carefully I’ve went back over this thread - there’s a lot of confusion going on. I’m not sure if I’m the one confused or the posters themselves. JavaScript is a cantankerous unusual language, and its implementation of the Object Oriented paradigm is not anything like compiled languages or PHP. Also, several of the examples given display a lack of understanding of javascript scope.
First off, I don’t get the parasitic example of Jeff Mott. I defined it in this html file, and corrected the syntax errors in it to arrive at the code below:
<!DOCTYPE html>
<body>
Open the Console.
<script>
function Parenizor(value) {
var that = this;
that.setValue = function (value) {
that.value = value;
return that;
};
that.getValue = function () {
return that.value;
};
that.toString = function () {
return '(' + that.getValue() + ')';
};
that.setValue(value);
return that;
}
ParenizorA = new Parenizor('first object');
console.dir(ParenizorA);
ParenizorB = new Parenizor('second object');
console.dir(ParenizorB);
console.dir(ParenizorA);
Parenizor.prototype.secondValue = 'I am attached after the fact';
console.dir(ParenizorA);
console.dir(ParenizorB);
ParenizorC = new Parenizor('third object');
console.dir(ParenizorC);
console.log(ParenizorA.value);
console.log(ParenizorA.secondValue);
ParenizorA.secondValue = 'Changed';
console.log(ParenizorA.secondValue);
console.log(ParenizorB.secondValue);
console.log(ParenizorC.secondValue);
</script>
</body>
</html>
Yes, you can have private members, but as shown by the last couple of console logs this isn’t the way to do it. I also find the that = this methodology to be sloppy. As for that = {}, this makes separate singleton objects that can’t have prototypes. Also it effectively makes the function a factory method. The ability of prototypical inheritance to effect a change across several objects is one of the most powerful parts of the language, and I strongly recommend avoiding the use of methods which sever this power without reason.
A function called with the new operator has an implicit return of this. Because of this reason you don’t need to issue a return from it. The outer function is essentially the constructor, and the other functions are the methods. Public members and methods are attached directly to the function and private ones are declared locally with var. For example:
<!DOCTYPE html>
<body>
Open the Console.
<script>
function SampleClass() {
this.publicVar = 'public';
var privateVar = 'private';
this.setValue = function (value) {
privateVar = value;
};
this.getValue = function () {
return privateVar;
};
this.addTheVars = function() {
return privateVar + this.publicVar;
};
var privateMethod = function() {
return 'I am private ' + privateVar;
};
this.testPrivate = function() {
return privateMethod();
};
this.callbackTestA = function() {
console.log(this.publicVar);
};
this.callbackTestB = function() {
console.log(this.publicVar);
}.bind(this);
}
var ExampleA = new SampleClass();
console.dir(ExampleA);
console.dir(ExampleA.getValue());
console.log(ExampleA.testPrivate());
var ExampleB = new SampleClass();
ExampleA.setValue('changed private');
console.dir(ExampleA.getValue());
console.dir(ExampleB.getValue());
setTimeout(ExampleA.callbackTestA,1000);
setTimeout(ExampleA.callbackTestB,1000);
</script>
</body>
</html>
This works because all the inner functions are closures as far as javascript is concerned. Because of how scope works in javascript they can see the variables in the same code block the function is declared in. Unfortunately the scope of “this” can be lost if the function is placed in an event callback (as seen in callbackTestA above), so it is sometimes necessary to bind the function scopes to the origin object using bind.
That can become tedious in large objects, so I’ve taken to using this technique.
for ( o in this) {
if (typeof this[o] === 'function') {
this[o] = this[o].bind(this);
}
}
Note the above however doesn’t work on private methods. They will have to be explicitly bound.
EDIT: Note - bind requires an emca5 shim to work on IE 8.