"Richard A. DeVenezia" <ra******@ix.netcom.com> wrote in message
news:bj************@ID-168040.news.uni-berlin.de...
<snip>
function Foo (argument) {
// Simpleton singleton
var callee = arguments.callee
if (callee.singleton != undefined)
return callee.singleton
if (this == window)
return new callee ( argument )
callee.singleton = this
var myName = callee.toString().replace (/\n/g, ' ').
match( /function\s(.*?)(\s|\()/ ) [1]
//alert ('my name is ' + myName)
installClassMethods ()
doBunchOfStuff()
As - doBunchOfStuff - is and inner function of this function and is only
called once does it need to be an inner function at all?
return
function doBunchOfStuff () {
var id = '_' + Math.random(0).toString().substring(2)
document.write ('<TABLE ID="' + id +
'"><TR><TD></TD></TR></TABLE>') var table = document.getElementById (id)
document.getElementById - may be widely implemented but it is not
universal. It is safer to test for the existence of this type of
function before using them to avoid error reports and allow for
controlled fall-back and clean degradation.
table.deleteRow (0)
deleteRow - may be HTML DOM specified and widely implemented but it is
not universal (even in browsers that are otherwise quite good DOM
implementations). You should test that method exists before using it to
avoid error reports and allow for controlled fall-back and clean
degradation. One fall-back option might be the DOM core - removeChild -
function called on the implied TBODY element.
var row = table.insertRow (table.rows.length)
var cell = row.insertCell ( row.cells.length )
Similarly insertRow and insertCell.
cell.innerHTML = '<B>Provided</B> by <I>convenience</I> of
innerHTML'
The test for innerHTML support is - if(typeof cell.innerHTML ==
'string') - though it may be implemented as read only (eg. Web Browser
2.0 on Palm OS as I recall (I don't have its docs to hand)). DOM node
insertion methods are more widely supported and, if implemented, will do
the job, so they could be the primary method with a fall-back to
innerHTML or the other way around.
cell.style.borderStyle = 'solid'
cell.style.borderColor = 'Black'
cell.style.borderWidth = '1px'
cell.onmouseover = function ( E ) { callee.over (this) }
cell.onmouseout = function ( E ) { callee.out (this) }
IE browsers are unable to garbage collect DOM elements and JavaScript
objects that form circular references with one another. Forming such
circular references produces a memory leak that persists until the
browser is shut down. Assigning these inner functions to properties of
the TD means that the TD has a reference to the functions, the functions
hold a reference to the closures that assigning the functions produces
and that closure has a reference to the TD held in the - cell -
property. A circular reference. At this point in the code this problem
can be averted by actively clearing the references to the DOM nodes from
the cell, row and table local variables (eg. cell = null; etc. at the
end of the function).
}
//--------------------------------------------------------------
function installClassMethods () {
//------------------------------------------------------------
callee.over = function (td) {
td.style.backgroundColor = 'black'
}
callee.out = function (td) {
td.transition = new callee.transition (td)
td.transition.doStart()
}
callee.transition = function (td) {
this.td = td
<snip>
That is another circular reference. The - new callee.transition(td) -
object is assigned as an expando property on the TD so the TD refers to
it, and the object holds a reference to the TD which it is a property
of. This circular reference is harder to break and would require the
expando property to be cleared. I notice that you are doing that later
on so this may not be a real problem (unless the page is unloaded before
the end of the sequence), but I don't see the need for the expando at
all. What would be wrong with:-
callee.out = fuction(td){
new callee.transitin(td).doStart();
};
- and drop the - this.td.transition = null - line from the doStep
function.
However, the event handling functions do not need to be inner functions
that call the public static functions of the constructor. You could just
assign the equivalent functions directly to the event handlers:-
cell.onmouseover = function(E){
this.style.backgroundColor = 'black'
};
cell.onmouseout = function(E){
new callee.transition(this).doStart()
};
- Obviously the references to the TD have changed from a passed
reference to the use of he - this - keyword (and I have removed the
expando) but otherwise the functions do the same task.
Also, although - new callee.transtion(this) - will work I don't think
that you need the transition constructor to be a property of the -
callee - constructor at all. If - transition - was an inner function
declaration:-
function Transition(td){
this.td = td;
this.step = 0;
this.interval = 10;
}
(or function expression - var Transition = function(td){ ...} -)
It would be possible to assign functions to its prototype (eg):-
Transition.prototype.doStart = function (){
thisObj = this;
thisObj.doStep();
this.timerId =
setInterval ( function () { thisObj.doStep() },this.interval );
};
- and use it as a constructor - new Transition(this); - wherever its
identifier was within the scope, ie. from within the "Foo" constructor
and any of its inner functions (such as the one assigned to
cell.onmouseout (the function that actually constructs the Transition
objects)).
Given your desire to keep the code independent of the identifier used
for the constructor, my pattern for this object would be:-
var Foo = (function(){
var singleton = null;
function Transition(){
. . .
}
Transition.prototype.doStart = function (){
. . .
};
Transition.prototype.doStep = function (){
. . .
};
return (function(argument){ //this is the singleton's constructor.
if (singleton)return singleton;
if (this == window){
return new arguments.callee( argument );
}
singleton = this
. . .
cell.onmouseover = function(E){
this.style.backgroundColor = 'black'
};
cell.onmouseout = function(E){
new Transition(this).doStart()
};
. . .
cell = null;
. . .
});
})(); //inline function expression execution
//assigning the singleton constructor to
//any identifier required.
- and now "Foo" has no public static properties at all.
Richard.