gruss "God's Boss"
Gehen wir doch einfach mal durch, was bei dem Aufruf von
new Foo(id);
(id
irgendein Wert) passiert:
...
Der Konstruktor-Aufruf endet, das erzeugte Objekt wird zurückgegeben.
Ergebnis: Drei Variablen (id
,that
,getSpecialId
), die via Closure erhalten werden, zwei Methoden inthis
.Demgegenüber:
...
Ich mache es kurz: Drei Variablen (id
,that
,getSpecialId
), die via Closure erhalten werden, zwei Methoden inthis
.falls ich mit meinen vermutungen richtig liege, geht die von mir
vorgestellte variante schonender mit arbeitsspeicher um, da jede
einzelne [[Foo]]-instanziierung weniger overhaed erzeugt, als es
der code Deines beispiels tut. vielleicht ist mein konstrukt sogar
schneller. klarheit schafft hier nur ein performance - test.
Dein Beispiel macht genau das Gleiche, nur komplizierter. Es müsste sogar langsamer sein, da ein zusätzlicher Funktionsaufruf nötig ist.
korrekt - ich hab' mir auch gerade eben den luxus gegoennt, dass ganze
ueberhaupt ersteinmal so schoen kausal zuendezudenken, wie von Dir just
vorexerziert.
Meine ursprüngliche Frage zielte darauf ab, bestimmte Teile
wirklich nur einmal im Prototype zu haben, damit bestimmte
Funktionen (aber eben nicht alle) nur einmal vorhanden sind
und nicht in jeder Objektinstanz.
wenn alles richtig gedacht war, leistet mein muster genau das.
Leider nicht.
jo, das draengte sich mir beim nachdenken ebenfalls mit erschrecken auf.
deswegen hackte ich auch gleich noch einen kurzen dreckigen test in die
tasten, um dann gespannt auf laufzeiten, cpu - und speicher-auslastung
unter den verschiedensten browsern zu achten.
das ergebnis - niederschmetternd! - ich fange mir, wie boese erahnt,
wirklich die volle breitseite:
- laufzeit fuer interface-loesung deutlich hoeher als fuer den in
einem guss formulierten konstruktor. - cpu-last fuer interface-loesung geringfuegig hoeher als fuer den in
einem guss formulierten konstruktor. - vemutlich ist das verhaeltnis bei der belastung des arbeitsspeichers
aehnlich (einfach mal die testdurchlaeufe extrem erhoehen).
die anwendung eines solchen interface/funktor/behavior-musters ist
demzufolge nur in genau den faellen sinnvoll, wo einheitliches verhalten
nachtraeglich auf voellig voneinander verschiedene objekte genagelt
werden muss.
den folgenden test bei interesse mal in die jconsole schmeissen:
Number.prototype.times=(function(fct,target){var i=-1,num=Number(this);num=((isFinite(num)&&(typeof fct=="function"))?(parseInt(num)):(i));target=(((typeof target=="undefined")||((typeof target=="obj")&&!target))?(null):(target));while(++i<num){fct.call(target,i,num,fct)}});
var FunkedFoo=(function(){var SpecialIdFunctor=(function(that){var getSpecialId=(function(){return(that.getId()+1)});this.showSpecialId=(function(){return getSpecialId()})});var FooConstructor=(function(id){SpecialIdFunctor.call(this,this);this.getId=(function(){return id})});return FooConstructor})();
var ClassyFoo=(function(id){var that=this;var getSpecialId=(function(){return that.getId()+1});this.showSpecialId=(function(){return getSpecialId()});this.getId=(function(){return id})});
alert("... pause ... proceed ... ");
(function (amountOfTestCycles, isCaching) {
var testCase, time, myId, myFoo, myFooList = [];
if (isCaching) {
testCase = (function () {
myFoo = new ClassyFoo(23);
myId = myFoo.getId();
myId = myFoo.showSpecialId();
myFooList.push(myFoo);
});
} else {
testCase = (function () {
myFoo = new ClassyFoo(23);
myId = myFoo.getId();
myId = myFoo.showSpecialId();
});
}
time = new Date();
(amountOfTestCycles).times(function (/*idx, len, fct*/) {
testCase();
});
time = ((new Date()) - time);
print("time for " + amountOfTestCycles + " testcyles with" + ((isCaching) ? ("") : ("out")) + " [[ClassyFoo]] instance caching : " + time + " msec");
})(50000);
alert("... pause ... proceed ... ");
(function (amountOfTestCycles, isCaching) {
var testCase, time, myId, myFoo, myFooList = [];
if (isCaching) {
testCase = (function () {
myFoo = new FunkedFoo(23);
myId = myFoo.getId();
myId = myFoo.showSpecialId();
myFooList.push(myFoo);
});
} else {
testCase = (function () {
myFoo = new FunkedFoo(23);
myId = myFoo.getId();
myId = myFoo.showSpecialId();
});
}
time = new Date();
(amountOfTestCycles).times(function (/*idx, len, fct*/) {
testCase();
});
time = ((new Date()) - time);
print("time for " + amountOfTestCycles + " testcyles with" + ((isCaching) ? ("") : ("out")) + " [[FunkedFoo]] instance caching : " + time + " msec");
})(50000);
alert("... pause ... proceed ... ");
(function (amountOfTestCycles, isCaching) {
var testCase, time, myId, myFoo, myFooList = [];
if (isCaching) {
testCase = (function () {
myFoo = new ClassyFoo(23);
myId = myFoo.getId();
myId = myFoo.showSpecialId();
myFooList.push(myFoo);
});
} else {
testCase = (function () {
myFoo = new ClassyFoo(23);
myId = myFoo.getId();
myId = myFoo.showSpecialId();
});
}
time = new Date();
(amountOfTestCycles).times(function (/*idx, len, fct*/) {
testCase();
});
time = ((new Date()) - time);
print("time for " + amountOfTestCycles + " testcyles with" + ((isCaching) ? ("") : ("out")) + " [[ClassyFoo]] instance caching : " + time + " msec");
})(50000, true);
alert("... pause ... proceed ... ");
(function (amountOfTestCycles, isCaching) {
var testCase, time, myId, myFoo, myFooList = [];
if (isCaching) {
testCase = (function () {
myFoo = new FunkedFoo(23);
myId = myFoo.getId();
myId = myFoo.showSpecialId();
myFooList.push(myFoo);
});
} else {
testCase = (function () {
myFoo = new FunkedFoo(23);
myId = myFoo.getId();
myId = myFoo.showSpecialId();
});
}
time = new Date();
(amountOfTestCycles).times(function (/*idx, len, fct*/) {
testCase();
});
time = ((new Date()) - time);
print("time for " + amountOfTestCycles + " testcyles with" + ((isCaching) ? ("") : ("out")) + " [[FunkedFoo]] instance caching : " + time + " msec");
})(50000, true);
... klarheit schafft hier nur ein performance-test.
»»
ich beuge mich auch jedem urteil; wobei noch viel interessanter
waere, wie die unterschiedlichen scripting hosts dabei abschneiden.
lieber Timo, danke fuer die lektion.
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:]