Ich dachte, es würde Spaß machen, meine Null-Padding-Erweiterung des Number.prototype in ein echtes Getter/Setter-Muster umzuschreiben. Nicht sehr schwierig. Am Ende habe ich diesen Code erhalten ( addSetter
y addGetter
sind nur Wrapper-Funktionen, die 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;
}
);
Funktioniert gut bei echten Zahlenobjekten:
var a = new Number(977);
a.leftPad0 = 10000;
alert('a => '+a.leftPad0); // a => 00977
Aber nicht für Zahlenliterale:
var b = 977;
b.leftPad0 = 10000;
alert('b => '+b.leftPad0); // b => undefined
Erreicht B also nicht den Einrichter? Oder wenn es den Setzer erreicht, ist es dann nicht eine Zahl?
Ich protokollierte dies in der Konsole innerhalb der Setter-Funktion:
this.constructor === Number // true
this instanceof Number //true
Oder wird der Getter nicht erreicht, oder wenn es erreicht wird, würde das Literal nicht eine Instanz von Number sein? Ich habe dasselbe innerhalb des Getters protokolliert. Alles gut und auch wahr.
Was kann also der Grund dafür sein, dass wir dieses Muster nicht mit einem Zahlenliteral verwenden können? Oder habe ich etwas übersehen?
Hinweis: Dieses Problem tritt nicht auf, wenn ich diese Prototyp-Erweiterung ('monkey patch') verwende:
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
[ bearbeiten ] Ich frage mich immer noch, ob wir dies als Fehler bezeichnen müssen, oder ob es dem/a Standard entspricht. Wie auch immer, ich habe jetzt mein eigenes Objekt dafür entwickelt:
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