Zuweisung zerstört Number-Objekt
Don P
- javascript
Hallo zusammen,
Habe ein unbequemes Verhalten von JS entdeckt:
Wenn man ein Number-Objekt mit "new Number(zahl)" erstellt, kann man ihm anschließend keine andere Zahl mehr zuweisen, ohne das Objekt zu zerstören, d.h. es wird dann immer in ein Primitive verwandelt. Beispiel:
var x = new Number(584);
x.einheit = 'Tage';
alert( [x, x.einheit, typeof x] ); // 584,Tage,object
x += 6;
alert( [x, typeof x, x.einheit] ); // 590,,number
Für einen bestimmten Zweck würde ich gerne mit Number-Objekten arbeiten, die um spezielle Eigenschaften erweitert sind, aber leider geht das so nicht :-(.
Gruß, Don P
Hallo,
Habe ein unbequemes Verhalten von JS entdeckt:
Das ist eigentlich ganz logisch. Ich weiß nicht, wie das in anderen Sprachen gelöst ist, aber es scheint mir unlogisch, dass a + b wieder das selbstidentische Number-Objekt a ergibt, nur eben mit neuem Wert. a=a+b wäre dann auch doppelt gemoppelt, weil es zu a=a auflösen würde.
Für einen bestimmten Zweck würde ich gerne mit Number-Objekten arbeiten, die um spezielle Eigenschaften erweitert sind, aber leider geht das so nicht :-(.
Ja. All diese Operatoren arbeiten mit Primitives und wandeln die Operanden ggf. um. Operator-Überladung gibt es in JavaScript nicht, also müsstest du dir einen eigenen Typ »Value« mit eigenen Methoden wie plus, minus usw. schreiben. Die operieren dann z.B. mit einem Number-Primitive als private Eigenschaft. valueOf und toString kannst du überschreiben, sodass sich das Objekt nach außen wie ein Number-Primitive verhält.
Mathias
gruss Don P, hallo und danke molily,
Für einen estimmten Zweck würde ich gerne mit Number-Objekten
arbeiten, die um spezielle Eigenschaften erweitert sind, aber
leider geht das so nicht : -(.Ja. All diese Operatoren arbeiten mit Primitives und wandeln die
Operanden ggf. um. Operator-Überladung gibt es in JavaScript nicht,
also müsstest du dir einen eigenen Typ »Value« mit eigenen Methoden
wie plus, minus usw. schreiben. Die operieren dann z.B. mit einem
Number-Primitive als private Eigenschaft. valueOf und toString
kannst du überschreiben, sodass sich das Objekt nach außen wie
ein Number-Primitive verhält.
genau, dass koennte dann z.b. so aussehen:
var DonPNumber = (function (num) {
num = Number(num);
this.valueOf = (function () {
return num;
});
this.toString = (function () {
return String(num);
});
this.sum = (function (val) {
num += Number(val);
});
});
var num = new DonPNumber(30);
num.unit = "apples";
num.sum(20);
alert(num); // 50 - true
alert(num.unit); // apples - true
alert(num + 300); // 350 - true
alert(num + "00"); // 5000 - true
so long - peterS. - pseliger@gmx.net
Hallo,
Vielen Dank @molily und @peterS.
Die Lösung ist ja ganz cool, tut mit wenig Code genau, was ich will :-).
Hatte natürlich bereits eigene Objekte gedacht, das erschien mir aber zu umständlich. Wenn die Lösung aber so einfach ist, werde ich sie wohl implementieren. Mehr als addieren und multipizieren muss ich nämlich nicht.
Gruß, Don P
gruss Interessierte,
den ganzen spass bekaeme man tatsaechlich auch auf den
namensraum des sprachkernobjekts [[Number]] verbacken,
welches sich dann um beliebige rechenoperationen fuer
[Number]-objekte erweitern liesse.
dabei geht keineswegs schon vorhandene funktionalitaet
verloren - [[Number]] *arbeitet* wie gewohnt, ist jetzt
aber maechtiger.
ob und warum mann so etwas machen muss bzw. will, sei
dahingestellt - im folgenden beispiel soll deshalb auch
nur der machbarkeitsbeweis gefuehrt werden - eine nette
spielerei, die das sprachkonzept etwas besser ausleuchtet,
gibt es allemal ab ...
... so - code:
Number = (function (coreFct) {
var constr = (function (num) {
num = coreFct(num);
this.valueOf = (function () {
return num;
});
this.toString = (function () {
return String(num);
});/*
this.toLocaleString = (function () {
});
this.toSource = (function () {
});*/
this.toFixed = (function (val) {
return coreFct.prototype.toFixed.call(num, parseInt(val, 10));
});
this.toPrecision = (function (val) {
return coreFct.prototype.toPrecision.call(num, parseInt(val, 10));
});
this.toExponential = (function (val) {
return coreFct.prototype.toExponential.call(num, parseInt(val, 10));
});
this.sum = (function (val) {
return (num += coreFct(val));
});
this.subtract = (function (val) {
return (num -= coreFct(val));
});
this.multiply = (function (val) {
return (num *= coreFct(val));
});
this.divide = (function (val) {
return (num /= coreFct(val));
});
/*
zum folgenden code siehe das newsgroups
thema »Funktion nicht als Konstruktor«
aus »de.comp.lang.javascript« verlinkt
auf »Google Groups«
[link:http://groups.google.com/group/de.comp.lang.javascript/browse_frm/thread/445e720541c03165/35818a7259c326e4?lnk=st&q=#35818a7259c326e4]
*/
//alert("constructor - alert(this) : " + this);
//alert("constructor - this.constructor : " + this.constructor);
return ((this.constructor !== arguments.callee) ? (num) : (this));
});
//constr.prototype = new coreFct; // nicht notwendig.
constr.MAX_VALUE = coreFct.MAX_VALUE;
constr.MIN_VALUE = coreFct.MIN_VALUE;
constr.NaN = coreFct.NaN;
constr.NEGATIVE_INFINITY = coreFct.NEGATIVE_INFINITY;
constr.POSITIVE_INFINITY = coreFct.POSITIVE_INFINITY;
return constr;
})(Number);
var num = new Number(30);
num.unit = "apples";
num.sum(20);
alert(num); // 50 - true
alert(num.unit); // apples - true
alert(num + 300); // 350 - true
alert(num + "00"); // 5000 - true
alert(num.subtract(35)); // 15 - true;
alert(num.multiply(.5)); // 7.5 - true;
alert(num.divide(.25)); // 30 - true;
num.unit = "pears";
num.sum(70);
alert(num); // 100 - true
alert(num.unit); // pears - true
alert(num + 300); // 400 - true
alert(num + "00"); // 10000 - true
alert(num - 20); // 80 - true
alert(num - "20"); // 80 - true
alert(num * .25); // 25 - true
alert(num / .25); // 400 - true
alert(num.toFixed(4)); // 100.0000 - true
alert(num.toPrecision(2)); // 1.0e+2 - true
alert(num.toExponential(3)); // 1.000e+2 - true
alert(typeof new Number("30")); // object - true
alert(typeof Number("20")); // number - true
alert(typeof parseFloat(new Number("4.5678"))); // number - true
alert(typeof parseInt(new Number(4.5678), 10)); // number - true
alert(parseFloat(new Number("4.5678"))); // 4.5678 - true;
alert(parseInt(new Number(4.5678), 10)); // 4 - true;
alert(Number.MAX_VALUE);
alert(Number.MIN_VALUE);
alert(Number.NaN);
alert(Number.NEGATIVE_INFINITY);
alert(Number.POSITIVE_INFINITY);
zum schnellen nachpruefen den gesamte codeblock
z.b. mal in die jconsole *hineinpasten*.
so long - peterS. - pseliger@gmx.net