cdmckay cdmckay - 1 month ago 8
Javascript Question

JavaScript "classes"

Are there any downsides to using a JavaScript "class" with this pattern?

var FooClass = function()
{
var private = "a private variable";
this.public = "a public variable";

var privatefn = function() { ... };
this.publicfn = function() { ... };
};

var foo = new FooClass();
foo.public = "bar";
foo.publicfn();

Answer

What you're doing in your example isn't the "class" pattern people think of in JS -- typically people are thinking of the more "normal" class model of Java/C#/C++/etc which can be faked with libraries.

Instead your example is actually fairly normal and good JS design, but for completeness i'll discuss behaviour differences you'll see between the private and public "members" you have

var private = "a private variable";
this.public = "a public variable";

Accessing private from within any of your functions will be quite a lot faster than accessing public because the location of private can be determined reasonably well just with a static lookup by the JS engine. Attempts to access public require a lookup, most modern JS engines perform a degree of lookup caching, but it is still more expensive than a simple scoped var access.

var privatefn = function() { ... };
this.publicfn = function() { ... };

The same lookup rules apply to these functions as with the above variable accesses, the only real difference (in your example) is that if your functions are called, say privatefn() vs this.publicfn(), privatefn will always get the global object for this. But also if someone does

f = foo.publicfn;
f();

Then the call to f will have the global object as this but it will be able to modify the private variable.

The more normal way to do public functions however (which resolves the detached public function modifying private members issue) is to put public functions on the prototype, eg.

Foo.prototype.publicfn = function() { ... }

Which forces public functions to not modify private information -- there are some times where this isn't an option, but it's good practice as it also reduces memory use slightly, take:

function Foo1() {
    this.f = function(){ return "foo" };
}

vs

function Foo2() {
}
Foo2.prototype.f = function(){ return "foo" };

In Foo1 you have a copy of the function object for every instance of Foo1 (not all the emory, just the object, eg. new Foo1().f !== new Foo2().f) whereas in Foo2 there is only a single function object.

Comments