This is the first post in a new series “The JavaScript Basics” that I hope will be interesting to you the reader, but more importantly I hope will foster some conversation.
I’ll be posting about (1) how I do things in JavaScript – from the basics of class definitions to optimizing 1000+ line applications – and (2) why I choose to do things this way. Hopefully our conversations will teach us both something new about this powerful client-side language. 😀
Class Definitions
Without further ado – let’s start with the basics: defining a class in JavaScript.
The Two Options for Class Definitions
There are two standard ways of defining a class. The simplest, and the one I’ve opted for, is to define a new class simply by defining a new function. The syntax is as follows:
Option 1
[code lang=’javascript’]
function myClass(contructor, arguments, here){
var privateVar = 12;
this.publicVar = “asdf”;
function privateFunction(){
return privateVar;
}
this.publicFunction = function(){
return this.publicVar;
}
}
[/code]
The above code defines a simple class with a private variable and function, and a public variable and function.
The other way to define a class, and the one used by the majority of JavaScript libraries out there, uses JavaScript’s prototype system.
Option 2
[code lang=’javascript’]
function myClass(contructor, arguments, here){
var privateVar = 12;
function privateFunction(){
return privateVar;
}
}
myClass.prototype.publicVar = “asdf”;
myClass.prototype.publicFunction =
function(){
return this.publicVar;
}
[/code]
This code also defines a class with a private variable and function and a public variable and function. And so, the question of the hour is…
Is There A Difference?
Absolutely. The differences between these two definitions is subtle but important, and each of these two ways of defining a class has its pros and cons. You should choose carefully when defining your class. In fact – the best way to define a class may be a merger of these two options, but I’ll talk about that at the end of the article.
Difference 1: Syntax
Obviously the syntax of these options is different, and at the end of the day, syntax is just syntax. It’s the mechanics of the language that determine which option is truly better. That said, the syntax of Option 1 is much much closer to class definitions in most other languages, and this is one reason I’m partial to Option 1. Still, personal preference should always take second place to script performance, security, etc.
I like Option 1 better, but it this shouldn’t sway our final choice.
Difference 2: Memory Consumption
The public functions in Option 1 are copied into each and every object that is instantiated from this class. This means that if you create 1000 objects from this class, each of those objects has its very own copy of every private and public function. This is potentially a ton of wasted memory and a huge con for Option 1!
In Option 2’s favor, the public functions defined in the prototype object are shared by all objects instantiated from this class. This means that if you create 1000 objects from Option 2 class definition, there’s still only 1 copy of the public functions in memory! Depending on your class and usage, this may be a substantial savings in memory.
Option 2 wins this round.
Difference 3: Access to Private Variables and Functions
In Option 1, the public functions always have access to the private variables of the class. However, in Option 2, the public functions do not have access to the object’s private functions and variables! I’ve set up an example html page (download) that demonstrates that this isn’t the case. Load it up with FireBug and you’ll see that it errors out.
This means that public functions defined in Option 2 cannot use private variables in the class. This is a huge loss for Option 2, and severely limits which functions can be defined like this.
Option 1 definitely wins this round.
Summary
So what’s the best way to define functions? I always opt for Option 1 because private variables and functions are a huge win. Private variables let you protect data from malicious scripts which may also be running on your page, and being able to properly define getter and setter methods for private properties is incredibly important – especially if you need to restrict access to private properties for more secure JavaScript code. Option 2 would force you to make all of your properties public, which leads to sloppy public interface for your class and usually weaker security (depending on your needs).
I’ve found that the definitive best way to define classes in Javascript is:
The very best way to define a class in JavaScript is to use Option 1 for all private properties, functions, and any public functions that access these private properties and functions. Any function that relies solely on the class’s public interface should be defined as Option 2, since this will help lower memory consumption of the overall program.
So the best way to define a class in JavaScript is a merger of Option 1 and 2!
Excellent set of articles. Clear, precise. Can’t wait to read further articles.
Also worth noting is Resig’s post here. He expands on Option 2 to provide a something like classical inheritance for classes.