So I've been doing some JavaScript class-like stuff such as
MyClass = function()
{
var x;
this.sayX = function()
{
alert(x);
}
}
but I've also seen
MyClass = function()
{
this.x = 0;
}
MyClass.prototype.sayX = function()
{
alert(this.x);
}
The big question is, am I still wasting memory space in today's JavaScript engines, or are they capable of seeing the duplication in my method and optimizing them out? The reason I ask is because I'd rather do proper data hiding and not have to prefix absolutely everything with 'this'.
So I've been doing some JavaScript class-like stuff such as
MyClass = function()
{
var x;
this.sayX = function()
{
alert(x);
}
}
but I've also seen
MyClass = function()
{
this.x = 0;
}
MyClass.prototype.sayX = function()
{
alert(this.x);
}
The big question is, am I still wasting memory space in today's JavaScript engines, or are they capable of seeing the duplication in my method and optimizing them out? The reason I ask is because I'd rather do proper data hiding and not have to prefix absolutely everything with 'this'.
Share Improve this question asked Nov 7, 2010 at 6:55 RandomInsanoRandomInsano 1,2602 gold badges17 silver badges37 bronze badges 3- As a note, you can use with(this) { } if it helps you out. – Conspicuous Compiler Commented Nov 7, 2010 at 7:02
- 4 DO NOT use "with". It's dangerous to use and will be removed from future implementations of ECAMScript. Cannot stress this enough - it is much better to pretend that "with" does not exist in JavaScript. – Hamish Commented Nov 7, 2010 at 7:14
- If you do it the first way, if you do any inheritance you'll need to be a lot more careful about what you do, how you mix the two techniques, when you call the super constructor, etc. – Chris Morgan Commented Nov 20, 2010 at 2:01
2 Answers
Reset to default 5The memory footprint of the first one will always be larger. Consider prototype
as a shared package of methods that all instances can use. It is effective because you don't create a new function for every instance, but you're reusing the existing method already in memory.
The good news is that the two ways you showed can be bined.
MyClass = function () {
var x;
// public method with access
// to private variables
this.sayX = function () {
alert(x);
};
}
// method that doesn't need access to private variables
MyClass.prototype.sharedMethod = function () {
// ...
}
But as far as you're dealing with small codebase, you shouldn't worry about memory usage. You can even use patterns like
// everything will be created for every
// instance, but the whole thing is nicely
// wrapped into one 'factory' function
myClass = function () {
// private variables
var x;
// private methods
function doSomethingWithX() {}
// public interface
return {
sayX: function () {
alert(x);
},
publicMethod: function () { .. },
// ...
};
};
Note, I intentionally changed myClass to lowercase, because it's no longer a constructor function and there's no need to use new
when invoking!
UPDATE - there's a third pattern which well suits your needs:
MyClass = function (x, y, whatever) {
this._init.apply(this, arguments);
}
// The prototype creates a scope for data hiding.
// It also includes a constructor function.
MyClass.prototype = (function () {
var x; // private
return {
_init: function (x_in) {
x = x_in;
},
sayX: function () {
alert(x);
},
// ...
};
})();
Revisiting this a huge amount later, but it turns out V8 is smart enough that it doesn't create multiple instanced of that function in the first method. Go hidden classes :D
http://www.youtube./watch?v=hWhMKalEicY