Rolf b: JavaScript Typsystem

Hallo,

ich bin im Javascript-Teil gerade darüber gestolpert, dass nicht zwischen primitiven Typen und Wrappertypen unterschieden wird. Im Artikel zu Boolean wurde munter mit new Boolean() hantiert, obwohl das nun überhaupt keinen primitiven Boolean-Typ erzeugt, sondern einen Wrapper dazu. Das kann zu bösen Fehlern führen, ein Beispiel dafür habe ich dort nun angeführt.

Bevor ich als "Neuling" hier eine Baustelle aufmache und umbaue (würde ich gern übernehmen), hätte ich gern die Meinung der "altgedienten" dazu - ist das dort so Absicht gewesen oder war dieser Unterschied einfach nicht so ganz klar?

Obwohl - "Neuling" - das ist so GANZ richtig nicht, ich nutze SelfHTML seit vielen Jahren :)

Rolf

  1. Hallo Rolf,

    ich bin im Javascript-Teil gerade darüber gestolpert, dass nicht zwischen primitiven Typen und Wrappertypen unterschieden wird. Im Artikel zu Boolean wurde munter mit new Boolean() hantiert, obwohl das nun überhaupt keinen primitiven Boolean-Typ erzeugt, sondern einen Wrapper dazu. Das kann zu bösen Fehlern führen, ein Beispiel dafür habe ich dort nun angeführt.

    Vielen Dank für Deine Initiative.

    Bevor ich als "Neuling" hier eine Baustelle aufmache und umbaue (würde ich gern übernehmen), hätte ich gern die Meinung der "altgedienten" dazu - ist das dort so Absicht gewesen oder war dieser Unterschied einfach nicht so ganz klar?

    Die JavaScript-Doku ist in (großen) Teilen noch eine Textübertragung aus der alten 8.12, in der der Schwerpunkt eher auf HTML und CSS lag.

    und umbaue (würde ich gern übernehmen)

    Vielen Dank im Voraus! Wir können wirklich viel Hilfe gebrauchen! Einige Sachen wie die Events haben wir bereits berichtigt (früher waren es HTML-Attribute, dann wanderten sie zu JavaScript und verloren das on-), die meisten Lücken gefült, aber es gibt noch viel zu tun.

    Obwohl - "Neuling" - das ist so GANZ richtig nicht, ich nutze SelfHTML seit vielen Jahren :)

    Das ist das Gute am Wiki, dass jetzt jeder mitmachen kann!

    Herzliche Grüße

    Matthias Scharwies

    --
    Es gibt viel zu tun - packen wir's an: ToDo-Liste gewünschte Seiten
    1. Hallo Matthias,

      danke für die Einladung. Dass jeder mitmachen kann, muss ja nicht heißen, dass sich jeder beliebig austoben sollte. Es gibt ja sicherlich eine Linie, der ihr folgt. :)

      Die Events sind übrigens auch heute noch eine spezielle Hölle für sich. Da darf man die Vergangenheit nicht einfach rauslöschen, damit Leute, die alten Code vor der Nase haben, dazu noch etwas nachlesen können. Ohne Frameworks wie jQuery lässt man von Events besser die Finger. Sind Verweise auf solche Bibliotheken hier statthaft?

      Das Typsystem nehme ich mir dann mal vor. Hoffentlich gibt's da keine Besonderheiten pro Brauser.

      Rolf

  2. Hallo Rolf

    ich bin im Javascript-Teil gerade darüber gestolpert, dass nicht zwischen primitiven Typen und Wrappertypen unterschieden wird. Im Artikel zu Boolean wurde munter mit new Boolean() hantiert, obwohl das nun überhaupt keinen primitiven Boolean-Typ erzeugt, sondern einen Wrapper dazu. Das kann zu bösen Fehlern führen, ein Beispiel dafür habe ich dort nun angeführt.

    Bevor ich als "Neuling" hier eine Baustelle aufmache und umbaue (würde ich gern übernehmen), hätte ich gern die Meinung der "altgedienten" dazu - ist das dort so Absicht gewesen oder war dieser Unterschied einfach nicht so ganz klar?

    Der Artikel von dem du hier offenbar sprichst ist unter Standardobjekte einsortiert, das heißt, der Gegenstand dieses Artikels ist grundsätzlich zunächst einmal der eingebaute Konstruktor Boolean.

    Bei einem Aufruf von Boolean wird als erstes die interne Operation ToBoolean mit dem Wert des Funktionsparameters durchgeführt, die abhängig davon, ob es sich um einen truthy value oder um einen falsy value handelt, den primitiven Wert true oder false zurückgibt. Bei einem normalen Aufruf ist dieser Wert auch der Rückgabewert von Boolean.

    In diesem Fall wird also eine Typumwandlung durchgeführt:

    const log = console.log.bind(console);
    
    const foo = Boolean({ });
    log(typeof foo); // boolean
    log(foo); // true
    
    const bar = Boolean(null);
    log(typeof bar); // boolean
    log(bar); // false
    

    Wurde Boolean hingegen mittels des Operators new als Konstruktor aufgerufen, dann wird ein Objekt erzeugt, in dessen interner Eigenschaft [[BooleanData]] der zuvor von ToBoolean zurückgegebene primitive Wert hinterlegt wird.

    Es wird also wie du sagst ein Wrapper Object erzeugt:

    const log = console.log.bind(console);
    
    const object = new Boolean([ ]);
    log(typeof object); // object
    
    const value = object.valueOf( );
    log(typeof value); // boolean
    log(value); // true
    
    const string = object.toString( );
    log(typeof string); // string
    log(string); // true
    

    Wird ein Objekt vom Typ Boolean erzeugt, dann erbt es von Boolean.prototype die Methoden valueOf und toString, welche die gleichnamigen Methoden von Object.prototype innerhalb der Prototypenkette verschatten.

    Die Methode valueOf kann verwendet werden um den Wert der internen Eigenschaft [[BooleanData]] des Instanzobjektes zu examinieren und toString erzeugt eine Stringrepräsentation dieses Wertes.

    Also, lange Rede kurzer Sinn, ich denke das sollte in etwa der rote Faden der Story sein. Davon abgesehen stimme ich dir voll und ganz zu, dass der Unterschied von primitiven Datentyp Boolean und dem Objekttyp Boolean möglichst klar kommuniziert werden sollte …

    … und ich würde mich sehr darüber freuen, wenn du diesen Artikel übernehmen würdest! :-)

    Vielen Dank und viele Grüße,

    Orlok

    1. Hallo Orlok,

      sehr interessanter Einblick, und gottlob war mir das nicht unbekannt sonst wäre ich jetzt rückwärts vom Stuhl gekippt. Der Wiki-Artikel muss (a) das Kippen vermeiden und sollte (b) trotzdem deine Infos transportieren. Naja, auf JavaScript-Engine Sourcecode-Ebene vielleicht nicht :)

      Was deine Logs oben nicht zeigen, ist, dass "new Boolean(true) === true" false ergibt, d.h. das gewrappte Objekt ist nicht identisch mit dem primitiven Wert. Und dass new Boolean(false) truthy ist, ist einfach gruselig...

      Was man in den Artikeln auch schreiben muss, ist, dass der Gebrauch der Wrapper die Ausnahme ist und nicht der Normalfall. Zu sagen, dass man new Boolean(true) hauptsächlich verwendet, um Rückgabewerte für Funktionen zu liefern, halte ich für schlicht falsch.

      Mal gucken wie ich hinkomme, ohne den Artikel in Boolean(Objekt) und Boolean(primitiv) zu teilen. Das wäre wohl die schlechteste Lösung.

      Rolf