I thougt it would be fun to rewrite my zero padding extension to the Number.prototype into a genuine getter/setter pattern. Not very difficult. I ended up with this code (addSetter
and addGetter
are just wrapper functions using prototype.__defineGetter__ / __defineSetter__
.
Number.addSetter('leftPad0',
function(v){
var len = (String(v).length - String(this).length)+1;
this._leftPad0 = new Array(len).join('0')+this;
}
);
Number.addGetter('leftPad0',
function(){
return this._leftPad0;
}
);
Works fine for real Number Objects:
var a = new Number(977);
a.leftPad0 = 10000;
alert('a => '+a.leftPad0); // a => 00977
But not for Number literals:
var b = 977;
b.leftPad0 = 10000;
alert('b => '+b.leftPad0); // b => undefined
So, doesn't b reach the setter? Or if it reaches the setter, isn't it a Number?
I logged this in the console from within the setter function:
this.constructor === Number // true
this instanceof Number //true
Or is the getter not reached, or when it's reached would the literal not be an instance of Number? I logged the same within the getter. All fine and true too.
So, what may be the reason that we are not able to use this pattern using a Number literal? Or have I missed something?
Note: this doesn't occur if I use this prototype extension ('monkey patch'):
Number.prototype.leftPad = function(base){
var len = (String(base).length - String(this).length)+1;
return new Array(len).join('0')+this;
}
alert( (977).leftPad(10000) ); // 00977
[edit] I still wonder if we have to call this a bug, or if it's following the/a standard. Anyway, I deviced my own object for this now:
function NumPL(val,pval,chr){
if (!(this instanceof NumPL)){
return new NumPL(val,pval,chr);
}
this._value = new Number(val||0);
this._padValue = pval || 10;
this.chr = chr || '0';
}
NumPL.prototype = {
get value(){
return this._value;
},
set padValue(v) {
this._padValue = v%10 === 0 ? v : 10;
},
set value(v) {
this._value = v;
},
get padLeft(){
var len = (String(this._padValue).length -
String(this._value).length)+1;
return new Array(len).join(this.chr)+this._value;
}
}
// Usage
var a = NumPL(977,10000);
alert(a.padLeft); //=> 00977
// or a real world example
var dat = new Date,
datshort = [dat.getFullYear(),
NumPL(dat.getMonth()+1).padLeft,
NumPL(dat.getDate()).padLeft]
.join('/');
alert(datshort); //=> 2011/05/19