Friday, December 12th, 2008

More JavaScript Inheritance; Prototypes vs. Closures

Category: Examples, JavaScript

<>p>Steffen Rusitschka has a nice detailed post on inheritance with JavaScript, different ways you can go, and side effects of the decision.

From,

javascript
< view plain text >
  1. var A = function(){}; // This is the constructor of "A"
  2. A.prototype.value = 1;
  3. A.prototype.test = function() { alert(this.value); }
  4. var a = new A(); // create an instance of A
  5. alert(a.value);  // => 1
  6. alert(a.test()); // => 1

to,

javascript
< view plain text >
  1. var C = function() {
  2.   // a private function
  3.   var print = function(msg) {
  4.     alert(msg);
  5.   };
  6.   this.value = 1;
  7.   this.test = function() {
  8.     print(this.value);  // calls our private function
  9.   };
  10. };
  11. var c = new C();
  12. alert(c.value); // => 1
  13. alert(c.test()); // => 1

He then goes on to share two helpers PClass and CClass that give you an easy way to choose which method you are looking for.

It is your choice which way of inheritance to chose for your specific problem. Speed+low memory = PClass; privacy = CClass.

Related Content:

  • Use JavaScript with the iPhone to create smart phone apps
    Objective-C remains the most prevalent iPhone development language, but JavaScript has been gaining traction as a viable alternative. You can use...
  • Ajax hype vs. reality
    Ajax is a powerful rich Internet application technology, but Burton Group cautions against overkill and notes that tools and frameworks for using it...
  • Ajax hype vs. reality
    Ajax is a powerful rich Internet application technology, but Burton Group cautions against overkill and notes that tools and frameworks for using it...
  • Ajax hype vs. reality
    Ajax is a powerful rich Internet application technology, but Burton Group cautions against overkill and notes that tools and frameworks for using it...
  • Delegates vs. interfaces in .NET
    The differences of using these two these two methods as callback...

Posted by Dion Almaer at 4:05 am
10 Comments

++---
2.4 rating from 27 votes

10 Comments »

Comments feed TrackBack URI

Or combination of this two with speed + low memory + privacy.

var C = (function() {
// a private function
var print = function(msg) {
alert(msg);
},
test = function() {
print(this.value);
};

return function() {
this.value = 1;
this.test = test;
};
})();
var c = new C();
alert(c.value); // => 1
c.test(); // => 1

Comment by MaLi — December 12, 2008

last row of original article:

“And keep in mind: it is not possible to mix both concepts inside one class hierarchy.

Happy coding :-)”

Comment by nunziofiore — December 12, 2008

I find Crockford’s articles more clear and informative than other people’s blogs.

Comment by Jordan1 — December 12, 2008

What’s the rationale behind using
var fnName = function() {};

instead of just
function fnName(){}

Personally I like it when I debug and don’t have to wade through all the anonymous functions created by the first method.

Comment by ProggerPete — December 12, 2008

Inheritance is something that has troubled me for a long time in JavaScript, I’ve gone through fazes where I’ve used most of the common techniques but the one that has stuck for me is simple mixins, just because it’s the one that feel most clean, natural and easy to read:

function myMixin(param){
var foo = param;
this.fooPlusTwo = function(){return foo + 2};
}

function MyClass(param){
myMixin.apply(this, param);
}

console.log(new MyClass().fooPlusTwo());

As with every JavaScript inheritance technique there is a downside, here the downside it the methods of the mixins are in the constructor rather than the prototype. In my experience there will be very few if any constructors in an application that will have enough instances to see much of a performance boost from placing methods in the prototype rather than the constructor.

In those cases you can use the same technique, and by adding a couple of extra lines make use of the prototype instead:

function myMixin(param){
//We only want to extent the prototype of our object once
//not every time it is instantiated
this.myMixin = true;

foo = param;
this.fooPlusTwo = function(){return foo + 2};
}

function MyClass(param){
if (!this.myMixin) myMixin.apply(MyClass.prototype, [param]);
}

console.log(new MyClass(2).fooPlusTwo());

To me this method of inheritance feels a lot like Python inheritance, except we’re using myMixin.apply(this) rather than MyClass.__init__(self)

Comment by ChrisInCambo — December 12, 2008

Admin: You should allow authors to edit their post within a set time period. I always forget this site removes the line breaks and white space at the start of a line. Let me put the above code in the tags and see how that looks:


function myMixin(param){
var foo = param;
this.fooPlusTwo = function(){return foo + 2};
}

function MyClass(param){
myMixin.apply(this, param);
}

console.log(new MyClass().fooPlusTwo());

Using prototype:


function myMixin(param){
//We only want to extent the prototype of our object once
//not every time it is instantiated
this.myMixin = true;

foo = param;
this.fooPlusTwo = function(){return foo + 2};
}

function MyClass(param){
if (!this.myMixin) myMixin.apply(MyClass.prototype, [param]);
}

console.log(new MyClass(2).fooPlusTwo());

Comment by ChrisInCambo — December 12, 2008

^^ Those tags don't really improve anything!

Comment by ChrisInCambo — December 12, 2008

Yeah, it’s really awkward that this blog doesn’t even have comment preview functionality.

Comment by ffreak — December 13, 2008

What’s the rationale behind using
var fnName = function() {};
instead of just
function fnName(){}

While in most engines they behave the same, according to ECMA they aren’t supposed to. The former is evaluated in-scope at runtime, as you’d expect with the flow of the code. The latter is evaluated when the script is loaded, before the rest of the code. The side effect is that this shouldn’t work as expected (but often will depending on the engine):

if(1) {
function fnName() {
doSomething();
}
} else {
function fnName() {
doSomethingDifferent();
}
}

If evaluated strictly according to the spec, you will get the latter function, even though that else statement will never be evaluated.

Comment by eyelidlessness — December 13, 2008

Oof. I wanted to add that you can also use…

var fnName = function fnName() {}

though I expect it would still have the same caveat as I described in my last comment.

Comment by eyelidlessness — December 13, 2008

Leave a comment

You must be logged in to post a comment.