0

Update: 2012.06.26 - See my conclusion bellow my original question.

I'm trying to figure out why this simple code doesn't initialize correctly. Yes, I'm from the Java world and I'm also a 'purist' and would like to do JavaScript properly.

Many (if not all) will recommend to declare the variables prefixed with a 'this' keyword and thus exposing all those variables without using proper setter and getter functions. To me this is unacceptable and does not reflect good OOP practice. They say JavaScript is an OOP language so why do people always try to bypass this I'll never understand!? But that's not the questions, so lets move on...

The problem with the following code is that when I run it in Chrome, it keeps telling me:

Uncaught ReferenceError: x is not defined

I could create a constructor which accepts the default values, but I'd rather not expose what the default value is suppose to be on those constructing the object (that is not good practice either). Also, during run-time, the setter methods would get invoked to change the 'x' and 'y' values for a specific instance. There are many 'Model' instances available at once!

So here is the simple code:

function Model() {
    var x = 3;
    var y = 'hello';
}

Model.prototype.getX = function() {
    return x;
}

Model.prototype.getY = function() {
    return y;
}

Model.prototype.setX = function(myX) {
    x =  myX;
}

Model.prototype.setY = function(myY) {
    y =  myY;
}

var model = new Model();

console.log("Model Y = '" + model.getY() + "'");
console.log("Model X = " + model.getX());
console.log("Model Y = '" + model.getY() + "'");

Thanks for your help...

Conclusion to the question (updated on 2012.06.26):

It is quite easy to conclude that what was requested (which happens to be something so simple) can not be done with JavaScript!

To my utmost surprise thought, as can be seen from the answers bellow, some will argue that since JavaScript does not support it, then you shouldn't need it or use it. Wow, that's really amazing!

I have argued for many years that JavaScript was not an OOP language and this simple question (and it's answers) goes to prove it.

So in the end it discusses me to admit defeat and you and I will both need to change our code to using the 'this' keyword for all class members. Once again, the language controls the programmer rather than the programmer controlling the language! And they wonder why over 2/3 of software projects fail every year!?

7
  • 3
    JavaScript isn't Java. The two languages are quite different, and in particular the object and inheritance models are completely different. Commented Jun 25, 2012 at 15:46
  • Private variables are only available in the scope that they are declared as well as within methods declared within that scope. Commented Jun 25, 2012 at 15:47
  • Apparently even Java cannot enforce privacy (tutorials.jenkov.com/java-reflection/…) Why should javascript? Commented Jun 25, 2012 at 15:47
  • @Pointy: Believe me, I know JavaScript is not Java! And they have different models, so are you working around to admitting what I'm trying to do is not possible? Commented Jun 25, 2012 at 19:08
  • @Esailija: What are you talking about? The first paragraph of your article clearly mentions the security sandbox! Reflection is a 'possible' way around it, if the security is left open, otherwise Java does 'private' members! So I guess from your justification that your saying JavaScript can not have private variables? Commented Jun 25, 2012 at 19:10

3 Answers 3

3

One way is to define getX and getY inside Model and not with prototype.

function Model() {
    var x = 3;
    var y = 'hello';
    this.getX = function(){return x;}
    this.getY = function(){return y;}
    this.setX = function(val){x=val;}
    this.setY = function(val){y=val;}
}

var foo = new Model();
console.log(foo.getX());

There are other ways of doing it, this is the simplest in my eyes.

Sign up to request clarification or add additional context in comments.

17 Comments

There are other ways of doing it; this is the only pattern which properly supports private variables, no? The downside of this is that each instance of Model has it's own copy of getX and getY, but this is only important if you instantiate a large number of Model objects.
I think so. But it multiplies the functions.
It would be easier just to use Dart or GWT than manage code written like this
@Jeach it is not widely accepted that information hiding is encapsulation (and therefore is not required for "OOP") see javaworld and wiki
@Jeach if we use distinct notions for information hiding (private stuff) and encapsulation (bundling data with methods that operate on that data), then javascript's object model fills all the fundamental concepts and features of OOP as described here en.wikipedia.org/wiki/Object-oriented_programming
|
2
function Model() {
    var x = 3;
    var y = 'hello';
}

This creates a local (useless) variable x but you want a property of your newly created instance of Model.

Use

  function Model() {
    this.x = 3;
    this.y = 'hello';
}

Model.prototype.setY = function(myY) {
    y =  myY;
}

This doesn't change your property. Use

Model.prototype.setY = function(myY) {
    this.y =  myY;
}

Yes, javascript and java are very different. Prefer conventions (like calling your private fields starting with _) instead of trying to enforce privacy.

6 Comments

As stated in the question, this will expose the variables and the OP does not want to do that. (-1)
private property aren't a good practice of javascript. Javascript isn't java.
Agreed, but this does not answer the OP's question and so is a bad answer. Maybe the answer you should be posting is that private properties aren't a worthwhile practice in JavaScript. That would answer the OP's question. This does not, hence the -1.
Even if you add a prefix to your variables (such as your suggested '_'), you still have those idiots who will read the variable directly or worst will set it's value directly without going through the setter. Note that I down-voted the answer because it goes directly against what the question requested. Abstaining is sometimes the right thing to do. But I guess some just want to add content for the sake of increasing their scores.
This answer fixed your code errors and suggested the way to do it that is the most adapted to javascript. I'm sorry you don't see it as helpful.
|
-2

You will need to use this

Model.prototype.getX = function() {
    return this.x;
}

2 Comments

I can't say I wasn't expecting this answer! :)
For the record, I was not the 'anonymous' coward that down-rated your answer! I would have let you know if it was me.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.