js/j12class.php

<html>
 <head>
  <title> <?php echo basename(__file__, '.php'); ?> </title>
 </head>
<body>
<h1>class C1 and C2</h1>
javascript has classes with inheritance, etc..
<ul id="uCla"> </ul>
<h1>class decs and expressions</h1>
<ul id="uDeEx"> </ul>
<h1>Prototype chain</h1>
however, javascript is purely prototype based, every object has a prototype it intherits from (code and data!)
<ol><li>the prototype of an object o is designated by o[[prototype]] and found by Reflect.getPrototypeOf(o) 
</li><li>a function f has an attribute prototype, which is passed to all objects created by new f
</li></ol>
<ul id="uProto"> </ul>
<h1>functions</h1>
function o with attributes
<ul id="uFun"> </ul>
<h1>objects</h1>
<ul id="uObj"> </ul>
<h1>instances</h1>
class instanciation and inheritance  is also implemented by prototype chains
<ul id="uInst"> </ul>
<h1>Source <?php echo __file__; ?> </h1>
<?php highlight_file(__file__) ?>
 </body>
    <script type="text/javascript">

function o(t) {
        o.u.innerHTML += '<li>' + t + '</li>'; 
    }
    o.to = function to(id) { 
        o.u = document.getElementById(id); 
    };

class C1 {
        constructor(nm, ag=10) {
            this.name = nm;
            this.age = ag;
        }
        toStr() {
            return 'nm=' + this.name + ' age=' + this.age + ' plus=' + this.plus + ' [[prototoype]].constructor=' + Reflect.getPrototypeOf(this).constructor.name;
        }
        static staticStr() { return 'class C1 static'; }
    }

class C2  extends C1 {
        constructor(nm, ag=20, plus="C2.plus.default") {
            super(nm, ag);
            this.plus = plus;
        }
    }


    o.to('uCla');
    let cU = new C1('walter', 62);
    let cV = new C1('jerome');
    o('cU ==> ' + cU.toStr());
    o('cV ==> ' + cV.toStr());
    cV.plus = "assign v.plus";
    o('cV ==> ' + cV.toStr());
    let cW = new C2('undC2');
    o('cW ==> ' + cW.toStr());
    o(' C1.staticStr() ==> ' + C1.staticStr());
    o('Reflect.getPrototypeOf(cU).constructor.staticStr() ==> ' + Reflect.getPrototypeOf(cU).constructor.staticStr());

    function deb(o) {
        function a2s(a) {
            let t = ''
            try {
                t = '' + a;
            } catch (e1) {
                try {
                    t = a.toString();
                } catch (e2) {
                    t = 'err[a2s ' + typeof a + ' e2==='+e2+' e1===' + e1 + '===]';
                }
            }
            return t.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
        }
        function short(o) {
            let t = typeof o;
            if (o == null || t == 'number' || t == 'string')
                return '' + o;
            if (t != 'object' && t != 'function')
                return t + '=' + o;
            if (! deb.m.has(o)) {
                deb.q.push(o);
                deb.m.set(o, t + '#' + (deb.m.size + 1))
            }
            return deb.m.get(o);
        }
        var r = short(o);
        if (deb.q.length <= 0)
            return r;
        r = '';
        while (deb.q.length > 0) {
            let a = deb.q.shift();
            let q = '</li><li>'+ short(a) + ' ' + a2s(a);
            let ex = q.indexOf('{');
            if ((ex > 0 ? q.substring(0,ex) : q).indexOf("HTML") >= 0) {
                r += q + "[deb doesn't show HTML to much stuff!]";
                continue;
                }
            r += q + ' [[prototype]]->' + short(Reflect.getPrototypeOf(a));
            let k = Reflect.ownKeys(a);
            for (var i=0; i < k.length; i++) {
                let l = k[i];
                r += ', ' + a2s(l);
                try {
                    r += '->' + short(a[l]);
                } catch (err) {
                    r += '-> err[' + err + ']';
                }
            }
        }
        return r.substr(9);
    } 

    (function (f) {
        f.m = new Map();
        f.q = [];
        nm = [Object, 'Object', Object.prototype, 'ObjProto', Reflect.getPrototypeOf(Object), 'Obj[[proto]]'];
        for (var i=0; i<nm.length; i+=2) {
            f.q.push(nm[i]);
            f.m.set(nm[i], typeof nm[i] + '#' + nm[i+1]);                
        }
    })(deb);
     
    o.to("uDeEx");
    o("cU ==> " + cU + ', typeof ' + typeof cU + ', constructor ' + cU.constructor + ', proto ' + Object.getPrototypeOf(cU));
    const ce1 = new class { p1 = 'prop1' ;}();
    o("new class ==> " + ce1 + ', typeof ' + typeof ce1 + ', constructor ' + ce1.constructor + ', proto ' + Object.getPrototypeOf(ce1)
        + '; p1 in=' + ('p1' in ce1) + ' hasOwn=' + Object.hasOwn(ce1, 'p1') + '; toString in=' + ('toString' in ce1) + ' hasOwn=' + Object.hasOwn(ce1, 'ptoString') );
    o.to("uProto");
    o(deb(Object));
    o("7 ==> " + deb(7));
    o("undefined ==> " + deb(undefined));
    o("'abc' ==> " + deb('abc'));
    o("NaN ==> " + deb(NaN));

    o.to("uFun");
    o("o ==> " + deb(o));

    o.to("uObj");
    function oo(t, a) { o(t + ' ==> {eins: ' +a.eins + ', zwei: ' + a.zwei + ', drei: ' +a.drei + ', vier: ' + a.vier + '}'); }
    let oA = {eins: 1, zwei: 'zwei'};
    oo("oA", oA);
    let oB = {drei: 3, vier: 'vier'};
    oo("oB", oB);
    let oC = Object.create(oA);
    oo("oC = create(oA)", oC);
    oA.zwei += 'Ass';
    oA.fun = function () { return 'oA.fun this.vier=' + this.vier; } ;
    oA.arr = ()  => 'oA.arr this.vier=' + this.vier ;
    oA.vier = 'A-assVier'
    oC.vier = 'C-assVier'
    oo("oA after ass fun=" + oA.fun(), oA);
    oo("oC oC.fun=" + oC.fun(), oC);
    oo("oA after arrow syntax ignores self arr=" + oA.arr(), oA);
    oo("oC oC.arr=" + oC.arr(), oC);

    o.to("uInst");
    o("cU ==> " + deb(cU));
    o("cW ==> " + deb(cW));
    C1.prototype.protAss = function (x) { return 'protAss(' + x + ', calls this.toStr=' + this.toStr() + ')' ; } ;
    o("cV.protAss('callEins') ==> " + cV.protAss('callEins'));
    o("cW.protAss('callZwei') ==> " + cW.protAss('callZwei'));

</script>

</html>