Matt Kruse wrote:
Larax wrote:
function SetEventHandler (element) {
element.onclick = function(event) {
// make something
}
}
Everything works fine, but I'm not sure about one thing - will the
onclick event handler be created in memory every time I call function
SetEventHandler
Yes.
Yes. More exactly (to correct OP's wording) on each SetEventHandler
call a new anonymous function will be created, allocated in the memory
and a reference to this anonymous function will be assigned to the
onclick event handler of the DOM [element].
But the previous function will be garbage collected since no reference still
exists to it.
Only if [element] argument points to the same DOM element on each call.
In this case indeed we are overriding onclick handler thus de-reference
the previous anonymous function. If that function was not referenced
anywhere else outside of the function scope (by say obj2.onclick ==
obj1.onclick somewhere) : then the previous anonymous function becomes
GC-available. It will be eventually garbage collected in the period of
time from one system tick to 60sec depending on the system load (60ms -
60000ms for Windows platforms).
Be careful - the example above creates a memory leak in IE.
No, it does not. You must be thinking of the nested functions such as:
function SetEventHandler (element) {
element.onclick = clickListener;
function clickListener(e vent) {
// make something
}
}
which indeed forms a rather nasty closure on each call so it leaks: on
any platform for any browser. This syntax still has its useful
application for particular circumstances - but it should avoided as
hell anywhere else. Alas "inner classes" in Cx and especially in Java
are the sign of a "cool programming style". Because of it – I guess-
a number of Cx/Java programmers jumped on nested functions (for the
lack of classes) to "remain cool even in primitive conditions" :-).
This is more of sociocultural than programming phenomenon: to be
investigated and punished by the project managers
In case of OP there is nothing of it though, so he's really "cool" :-)
Besides of the known blogs of Eric Lippert it can be also an
interesting additional reading:
<http://msdn.microsoft. com/library/default.asp?url =/library/en-us/ietechcol/dnwebgen/ie_leak_pattern s.asp>
If you create a global function and merely assign it to the onclick, the
memory leak will not occur.
1) That is the oldest well proven way: but it raises the question of
namespace conflicts. So if this way is followed, some additional
notation is needed for functions. The oldest and the simplest one is
the Macromedia notation: two caps producer id - underscore - name:
function LX_clickListene r() {
// make something
}
function LX_SetEventHand ler(element) {
element.onclick = LX_clickListene r;
}
As it's know (or not known so now you know) the opposition of "cool"
and "lame" ("no cool") and overall questions of the current fashion do
play a very important role in the programming. Sometimes they are even
prevailing over purely technical considerations. I may try to explain
it by the specifics of the "programmin g society" with traditionally
high amount of whom either just stopped to be teenager or remained a
bit of teenager no matter what is her real age. This floody preface was
just to say that this programming style (with stay-alone functions)
considered being out of fashion. By the performance it's the most
effective one, but... no cool :-) in case if you decide to show it to
someone. Another problem is that since 1995 a great amount of libraries
has been written and it is not a wander to see a modern page loading
3-5-more modules from different producers. It means that the old two
caps prefix may be too short to exclude with enough of insurance
namespace collisions. That is *not* a crucial default of any kind: just
another aspect to pay attention to.
2) The next way to use static methods is of course the native
JavaScript inheritance mechanics. By adding some method into prototype
you will get this method presented in each object instance (over the
instance prototype chain).
<html>
<head>
<title>Untitl ed Document</title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<script type=”text/javascript”>
function SetEventHandler (element) {
this.element = element;
element.onclick = this.clickListe ner;
}
SetEventHandler .prototype.clic kListener = function(){
window.alert(th is.id);
}
function init() {
var JSxDOM = new SetEventHandler (document.getEl ementById('prob e'));
}
window.onload = init;
</script>
</head>
<body>
<p id="probe">Clic k me</p>
</body>
</head>
There are a few drawbacks of this in your particular situation.
a) prototype applies to the object instances produced by the
constructor, not to the constructor itself. It means that in order to
activate the prototype chain you have to create new object instance
over [new] (unless you are hacking JavaScript instead of *using* it).
That is not always necessary by the program logic - say I see it as not
really necessary in your case (though I may be wrong).
b) DOM interface and JavaScript object are all separate entities
(despite of what Gecko thinks about it :-) That means that within the
conventional programming model (bindings/behaviors aside) you have to
deal then with combos (wrappers) like JSxDOM in the sample above which
is a script object but having a reference on DOM Element. Often it is
not necessary by the program logic plus it requires extra attention
with proper reference removal: so do not create a circular reference
where JS object refers to DOM element and DOM element refers to JS
object.
Say in the sample above we can remove this.element = element; from the
constructor as we do not plan to use it. But it makes the situation
even more bad: i) we are creating an object just to "drop" it right
away which is a bad programming practice; ii) after we are leaving
init() function, JSxDOM - as being local variable - will be garbage
removed but the object it refers to will *not*: it is still referenced
in DOM Element over its clickListener method so it will not garbage
available until DOM Element onclick handler is overridden. That is not
a crucial problem, but easy to forget about.
3) Static methods over function augmentation. What is what I'm using
the most often: but *please* don't take it as "all time best". OK, I
think it is :-) but I'd like to see more critics on it.
<html>
<head>
<title>Untitl ed Document</title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<script>
function SetEventHandler (element) {
element.onclick = SetEventHandler .clickListener;
}
SetEventHandler .clickListener = function(){
window.alert(th is.id);
}
function init() {
SetEventHandler (document.getEl ementById('prob e'));
}
window.onload = init;
</script>
</head>
<body>
<p id="probe">Clic k me</p>
</body>
</html>