Don P: Zuweisung zerstört Number-Objekt

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

  1. 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

    1. 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

      --
      »Because objects in JavaScript are so flexible, you will want to think differently about class hierarchies.
      Deep hierarchies are inappropriate. Shallow hierarchies are efficient and expressive.« - Douglas Crockford
      ie:( fl:) br:> va:( ls:& fo:) rl:) n3;} n4:} ss:} de:µ js:} mo:? zu:]
      1. 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

      2. 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

        --
        »Because objects in JavaScript are so flexible, you will want to think differently about class hierarchies.
        Deep hierarchies are inappropriate. Shallow hierarchies are efficient and expressive.« - Douglas Crockford
        ie:( fl:) br:> va:( ls:& fo:) rl:) n3;} n4:} ss:} de:µ js:} mo:? zu:]