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, '&').replace(/</g, '<').replace(/>/g, '>');
}
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>