I'm starting some work on a rather large JS project and want to make sure I structure the code cleanly and efficiently. I've been reading up on a ton of different approaches to OOP in JS and haven't found one that I really like.
I appreciate the performance improvements offered by using the prototype
property, but when you try to add true private methods and variables into the mix it gets rather messy. On the other hand, I really like the closure
approach, but I'm not comfortable with the decreased performance. I looked into the module
pattern but found it to be pretty verbose. Is there a happy medium somewhere?
To illustrate what I'm struggling with, here are two very small sample classes:
Point Class:
function Point(x, y) {
this.x = x;
this.y = y;
}
// Get the x coordinate.
Point.prototype.getX = function() {
return this.x;
}
// Get the y coordinate.
Point.prototype.getY = function() {
return this.y;
}
// Get the (x, y) coordinate.
Point.prototype.getXY = function() {
return {x: this.x, y: this.y};
}
// Set the x coordinate.
Point.prototype.setX = function(x) {
this.x = x;
}
// Set the y coordinate.
Point.prototype.setY = function(y) {
this.y = y;
}
// Set the (x, y) coordinate.
Point.prototype.setXY = function(x, y) {
this.x = x;
this.y = y;
}
User Class:
function User(guid) {
var guid = guid;
// Return the user's GUID.
this.getGuid = function() {
return guid;
}
}
There will potentially be thousands of point objects in use at any one given time, so I feel like the prototype
approach is the best option there. However, if I wanted to add any validation to the setting of coordinates, it could be bypassed by just calling Point.x = <value>
. Similarly, I'll likely be calling Point.getXY()
the majority of the time, which will be constructing new objects for what are essentially public properties. Should I get rid of the notion of getters and setters for the Point
class and just have it create completely open, public objects? This seems wrong in the context of OOP.
For the User
class, I want to store a GUID internally such that it can be requested but never modified. This can't be done with the prototype
approach (unless I'm missing something), so I'm forced into using some sort of closure
. I foresee having on the order of hundreds of users active at once, so the performance isn't as important as it is with the Point
class. However, I don't really want to switch between different types of OOP styles throughout the codebase.
So, as a general question, is there an approach to OOP in JS that I'm missing which would allow me to use the prototype
property while cleanly privatizing select functions and variables? Or, am I looking in the wrong direction? Should I be approaching this differently?