24 December 2007

What Hi-Fi disappoint on Lossless

In the Sound Advice section of the Jan 2008 issue of What Hi-Fi a reader asks what the best portable player and file format is for maximising digital audio quality. The response is essentially buy an iPod and use Apple Lossless. Whilst I agree the iPod's audio hardware is very good, I don't think its virtually proprietary encoding algorithm is something What Hi-Fi should be encouraging people to use.

They later go on to say that you could buy a device from Creative and use "one of the other lossless formats" but they don't give any examples of other formats or mention that the only lossless formats the current Creative products support are WMA (Microsoft Lossless) and AAC (Apple Lossless).

All in all I'm disappointed that a magazine that professes to be unbiased and impervious to the corporates is so casual about recommending proprietary formats which facilitate consumer lock-in. In my opinion they should be promoting the open source formats and marking the products they review down for only supporting propretary technologies. Decreasing consumer choice is, after all, a negative factor and the corporates shouldn't be allowed to get away with it.

On the plus side, from 31st Dec, 7 Digital will be offering Radiohead's In Rainbows in FLAC format click here for more.

10 December 2007

Reference types in prototype declaration - JavaScript gotcha

I've recently started doing some heavy duty JavaScript, including messing around with constructors, prototypes, lamdas, closures etc. I started off creating a few classes by creating a constructor function and then defining its prototype using object-literal notation as it means your code looks quite like class declarations in other OO languages.

Here is a simple example without any methods, just with two member variables:

function MyClass(){}
MyClass.prototype = {
 iNum: 0,
 sStr: 'Derek'
};

var oA = new MyClass();
var oB = new MyClass();

// oA: iNum -> 0, sStr -> Derek
// oB: iNum -> 0, sStr -> Derek

oA.iNum++;
oA.sStr += ' Fowler';

// oA: iNum -> 1, sStr -> Derek Fowler
// oB: iNum -> 0, sStr -> Derek

All seems well, however, upon adding some reference types to the prototype things get a bit strange:

//...

MyClass.prototype = {
 iNum: 0,
 sStr: 'Derek',
 aAry: []
};

//...

// oA: aAry.length -> 0
// oB: aAry.length -> 0

oA.aAry.push('test');

// oA: aAry.length -> 1
// oB: aAry.length -> 1

Adding an element to aAry of oA has added it to oB's aAry too. "Odd", I thought, so I did a little more investigation:

// MyClass.prototype.aAry.length -> 1

The array property of the instances is pointing back to the property of the prototype. In other OO languages all member variables within the class declaration are copied into the instances, it is only static variables and method implementations that are shared between them. These JavaScript variables seem to be neither member nor static, they are member if value types and static if reference types. Next I tried looping though the properties and testing hasOwnProperty:

for(var sProp in oA){
 // oA.hasOwnProperty(sProp)
}

Before the assignments all the properties return false, that they are not member properties but reside within the prototype. Following the assignment however iNum and sStr return member and only aAry still claims to be prototype.

This behaviour isn't a bug in an implementation either, it is consistant in all the browsers but after having a quick look in the ECMA-262 doc i'm still none the wiser about why this is the case. Anyone who can shed light on this please comment below.

The solution

The solution to this is to create all member variables using the this keyword in the class constructor thus:

function MyClass(){
 this.aAry = [];
}

This ensures that the variable is created upon the new instance and you don't get any sharing problems.