June 2007 Archive

Private static class vars in javascript

By Luke Smith on June 19, 2007 9:40 PM

Here's an addition to the recently named Module Pattern. Let's add private static class vars.

Let's assume we want to create an object class that will be used via the new operator, but there's a need to have a shared but private data space between instances. Here's how:

Example code

// always contain your code in a namespace
var LSN = { example : {} };

LSN.example.Foo = function () {
    // vars and methods declared in this scope will be shared by instances
    var static_bar = 0;

    // private static functions
    function incrementBar() { ++static_bar; }
    function getBar() { return static_bar; }

    // Create a function that will be returned as the Foo class constructor
    // referencing static vars and methods along with instance 
    function InstanceConstructor(instance_seed) {
        // instance private variable
        var instance_bar = instance_seed;

        // instance private method (until exposed in the returned object)
        function incrementInstanceBar() { --instance_bar }

        // instance private method affecting the class static var
        function splitStaticBar() { static_bar = Math.floor( static_bar / 2 ); }

        return {
            incrementStaticBar : incrementBar, // method affecting static class vars
            decrementStaticBar : function () { --static_bar }, // another, less efficient way
            splitStaticBar : splitStaticBar, // slightly less inefficient way, but still not preferable
            getStaticBar    : getBar, // get the shared static value

            incrementInstanceBar : incrementInstanceBar, // method affecting instance private var
            decrementInstanceBar : function () { --instance_bar }, // another, less efficient way
            getInstanceBar : function () { return instance_bar } // get the instance private var
        }
    }

    // return the function that will be used to construct the instances
    return InstanceConstructor;
}();

// Proof is in the pudding.  Create two instances of Foo
var t1 = new LSN.example.Foo(10);
var t2 = new LSN.example.Foo(2);

t1.getStaticBar(); // returns 0
t2.getStaticBar(); // returns 0

// Have one instance modify the private class var
t1.incrementStaticBar();
t1.getStaticBar(); // returns 1
t2.getStaticBar(); // also returns 1

for (var i = 0; i < 5; ++i) {
    t2.incrementStaticBar();
}

// Modify the static var with a method declared in the instance function scope
t1.splitStaticBar();
t1.getStaticBar(); // returns 3
t2.getStaticBar(); // also returns 3

// Play with instance variables as well
t1.getInstanceBar();  // returns 10
t2.getInstanceBar();  // returns 2

t1.incrementInstanceBar();
t1.getInstanceBar(); // returns 11
t2.getInstanceBar(); // returns 2

Points of interest

It's a pretty simple change from the basic instance creator function. Just wrap the instance creator function in another function—what I'm calling a class creator function. All vars declared in the class creator function scope are shared across all instances created with the returned instance creator function.

The methods affecting the class vars can be declared in the instance creator function scope, but I think it's cleaner to have the class var accessor methods in the class creator scope unless they're also modifying instance variables.

In my example, I chose to use prototypeless instance creation, returning a simple object with function refs to modify private class and instance data. It is possible to use a prototyped instance creator function and assign methods to the prototype that will affect the private class vars (but not the private instance vars). For example

    ...
    function InstanceConstructor(instance_seed) {
        // instance private variable
        var instance_bar = instance_seed;

        // instance private method (until exposed in the returned object)
        function incrementInstanceBar() { --instance_bar }

        // instance private method affecting the class static var (dead code.  see NOTE below)
        function splitStaticBar() { static_bar = Math.floor( static_bar / 2 ); }

        this.incrementInstanceBar = incrementInstanceBar;
        this.decrementInstanceBar = function () { --instance_bar };
        this.getInstanceBar = function { return instance_bar }
    }
    InstanceConstructor.prototype.incrementStaticBar = incrementBar;
    InstanceConstructor.prototype.decrementStaticBar = function () { --static_bar };
    InstanceConstructor.prototype.getStaticBar = getBar;
    // NOTE: we can't reference the splitStaticBar function, since it was declared in the instance creator function scope, but we're back in class creator scope

    return InstanceConstructor;

Practical uses?

This would be useful when used with prototypeless instance construction where you want to create only one instance for a given set of construction params, and redistribute the cached instances on future calls to new. At the moment, I'm tired and that's all I can come up with. I'll let smarter people devise clever uses for it.

Update

Richard Cornford sent me an excellent and far more thorough write up on the idea. Good reading. I found the use of the much derided with particularly intriguing.

I'm a dad!

By Luke Smith on June 10, 2007 1:59 PM

My first child, a boy, was born Saturday morning at 4:17am. Like all other biological grandchildren of my parents, he was male, about 7lbs 13oz, and 21inches long. Come to think of it, all their children were boys as well (though I'm not sure on my and my brother's stats). I guess there's some pretty strong boy genes in the family :)

Sparing details, the birth experience was quite simply the most difficult thing I've ever participated in. Last night I got some decent rest for the first time since Wednesday night. It's amazing what necessity can allow you to do. Heidi's recovering nicely and feeling great.

We learned the gender at the birth, but most of Heidi's family and our friends were certain it would be a girl. As such, we had a few girls names picked out, but had only barely agreed on one boy's name. Liam Eleki. We haven't yet decided that would be his name as I'd like to get to know the person first. Funny, writing the name for the first time makes me feel a sense of decisiveness about the choice, as well as thinking "hmm, that's ikele mail backwards". I just looked up the history and meaning of Liam, and I guess it is the Scottish form of William, a germanic of Willhelm. Now I can't stop thinking about the infamous Willhelm scream. I'd rather my child not be associated with screaming, but it is pretty amusing. I think the name means "strong protection" which is nice enough. Not that anyone cares or references the origin or meaning of a name in day to day life. Eh.

He's been healthy and strong the whole pregnancy, and continues to be so. Like I've heard happens to every new parent, I fell in love with the guy at first sight. He's a good looking kid, if I do say so myself :)

I reasoned out this morning that children probably always look beautiful to their parents because mom and dad are used to seeing themselves in the mirror and looking at their spouse (presuming), whom they obviously care immensely for. The baby looks like two people they love, so of course it's beautiful. Still, that's one cute little man. Everyone's entitled to their own opinion, of course, but they'd be wrong if they didn't agree with me :)

I'm somebody's papa.

Wow.

Update: It's official. Liam Eleki Smith. I even bought him his own domain :)

Yay Photoshop. Boo Adobe

By Luke Smith on June 3, 2007 7:17 PM

On April 26th, I placed my order for Adobe Photoshop CS3. Naively, I assumed since it was software, that I'd get it either immediately, or within a couple days. Silly me. After about a week and a half, Heidi mentioned that our card hadn't been charged for it, so I got a little nervous. I'd purchased it with a 50% off coupon that had expired April 30th. Fortunately, I had the receipt email (for what that's worth).

Still, I visited Adobe.com looking for a customer service number to call and verify they had my purchase on file. They'd nicely put an info box above the contact numbers telling people that they just started shipping CS3, so it would be two to four weeks before they got caught up with the backlog. Two to four weeks. Well, that sucks. I'd waited until the very last minute on that coupon so we could put off the financial impact, and now I got to wait another month? Swell.

It arrived May 29th, and I was elated. I woke up early on the the 30th, like a kid on Christmas, and ran down to my office to install it before work. I expected a straight forward drag-the-icon-to-the-applications-folder style install, but nope. Still, no biggie. I'm just happy I have it. It could take an hour to install and I'd be fine.

...Boy this is taking a long time to install...

Done! Righto, let's get this boy registered and activated in my name as a legit Photoshop owner. I've waited years for this day.

Aaaand the activation process spits out an error and sends me to the "Register over the phone" method. Hmm, that's lame. I call the number and speak to a lovely woman who politely sends me through the "If you're a pirate, which you probably are, we will kick you in the nuts, insult your mother, and send you to jail with a shirt that says 'I like guys'" verification process. I understand their position (for the most part), and hey, I'm legit damn it, so I can lift my chin and answer honestly.

I explain the situation, inform her a few times that "no, I didn't download the software, it arrived in the mail", then provide my serial number a few times only to find out that it's apparently invalid. Invalid? Come again? This must be a confusing situation for them. I mean, I'm clearly a pirate, since I'm trying the old invalid serial number trick, but damn if my credentials don't check out. I must have gotten the real owner's life story. It's the only explanation.

She transfers me to another nice lady, who asks a few more verifying questions ("Yes, I understand that you'd say bad things about my mom"), then has me provide my serial number a few more times. Yep, invalid. Nice. Well no problem, they can email me a new serial number.

In 24 to 48 hours.

They must have a large un-air-conditioned warehouse filled with underage former Nike "employees" assembling new serial numbers by throwing colored pegs at a distant lite-brite board. Seriously, have you ever heard of computers? You know, those things that you write really expensive programs for? Yeah, they can do that instantly.

Regardless, given that I called them at 8am, that means the kids should have my colorful new serial number ready by end of day Thursday.

It's Sunday, June 3rd, and I have a nice shiny new box and disk case with a bad serial number on it, and a very expensive "Trial Version" of Photoshop CS3 running on my computer. I'm hoping Adobe's version of 24-48 hours doesn't stretch beyond the trial period.

Maybe they ran out of light pegs.

Update: I called Adobe on the 7th to discover that they'd effectively lost my request for reserialization and they'd get that going for me (again) within the next 24-48 hours. Mind you, this was after spending roughly an hour on hold and being tossed back and forth between customer service and technical support spitting out the invalid serial number a few times at each step. The pinnacle was having an elder customer support rep say I'm sorry. I can't work and talk at the same time like young kids. I was filled with confidence that this time they'd get it right.

Well, it just so happens they did. I finally got my serial number on the 11th. I also received an email request to take a customer service survey. I think I might just fill that out.

ls.n

LucasSmith.name

Luke and Liam

I'm Luke. I am a front end engineer at Yahoo! on the YUI team.

Mostly I write about code stuff, but occassionally I'll mix in some real life. You've been warned.

Archives

Tags

Feeds

Subscribe to feed Recent entries

Content licensed under Creative Commons

Code licensed under BSD license

©2005 - 2010 Lucas Smith

Powered by Movable Type