Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Javascript (http://www.velocityreviews.com/forums/f68-javascript.html)
-   -   Function declaration inside other function (http://www.velocityreviews.com/forums/t928595-function-declaration-inside-other-function.html)

Larax 12-07-2006 03:50 PM

Function declaration inside other function
 
Best explanation of my question will be an example, look below at this
simple function:

function SetEventHandler(element)
{
// some operations on 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, or browser will create only one instance and use it
for every element ? I can of course make that event handler as global
function and assign only reference to onclick event, but I'm just
wondering if there is any diffrence between these two methods.

Thanks for help


Matt Kruse 12-07-2006 04:39 PM

Re: Function declaration inside other function
 
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.

But the previous function will be garbage collected since no reference still
exists to it.

Be careful - the example above creates a memory leak in IE.

Why? Because the element has a reference to the function, and the function
(through its scope chain) has a reference to the element. This circular
reference cannot be detected by IE and it causes a memory leak. Read up on
it and use the Drip tool to detect memory leaks like this.

If you create a global function and merely assign it to the onclick, the
memory leak will not occur.

--
Matt Kruse
http://www.JavascriptToolbox.com
http://www.AjaxToolbox.com



Richard Cornford 12-07-2006 05:04 PM

Re: Function declaration inside other function
 
Larax wrote:
> Best explanation of my question will be an example, look below
> at this simple function:
>
> function SetEventHandler(element)
> {
> // some operations on 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,


That is very likely. Javascript is allowed to "join" function objects
if it can know that doing so will make no difference (which would be
the case here as the inner function does not make use of any of the
formal parameters or local variables of the function that contains it).
In practice web browser javascript engines don't seem to ever do this
and instead always create a new and unique function object with each
evaluation of a function expression. Probably the overheads in
determining that "joining" the successive function objects would be
safe too great).

> or browser will create only one instance and use it
> for every element ?


That would be allowed to here, but there is no evidence of any browsers
doing so.

> I can of course make that event handler as global
> function and assign only reference to onclick event, but I'm just
> wondering if there is any diffrence between these two methods.


The assigning of the inner function forms a closure. If there is no
reason for forming a closure, the issues that may follow (IE's memory
leak issue) and the creation of the multiple function objects make
using the inner function undesirable. See:-

<URL: http://jibbering.com/faq/faq_notes/closures.html >

Richard.


Larax 12-07-2006 06:51 PM

Re: Function declaration inside other function
 
Thanks for your explanations, I could have ran into serious problems
with the IE memory leak as I'm assigning quite a lot of event handlers
that way.

Larax


VK 12-07-2006 10:08 PM

Re: Function declaration inside other function
 
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(event) {
// 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_patterns.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_clickListener() {
// make something
}

function LX_SetEventHandler(element) {
element.onclick = LX_clickListener;
}

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 "programming 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>Untitled 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.clickListener;
}

SetEventHandler.prototype.clickListener = function(){
window.alert(this.id);
}

function init() {
var JSxDOM = new SetEventHandler(document.getElementById('probe'));
}

window.onload = init;
</script>
</head>

<body>
<p id="probe">Click 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>Untitled 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(this.id);
}

function init() {
SetEventHandler(document.getElementById('probe'));
}

window.onload = init;
</script>
</head>
<body>
<p id="probe">Click me</p>
</body>
</html>


Richard Cornford 12-07-2006 11:59 PM

Re: Function declaration inside other function
 
VK wrote:
> Matt Kruse wrote:
>> Larax wrote:
>>> function SetEventHandler(element) {
>>> element.onclick = function(event) {
>>> // make something
>>> }
>>> }

<snip>
>> Be careful - the example above creates a memory leak in IE.

>
> No, it does not.


Yes it does. The [[Scope]] property of the function object resulting
from the evaluation of the function expression refers to a scope chain
that includes the Activation/Variable object of the function execution
context it was created within. That Activation/Variable object has an -
element - property that is the result of the declared formal parameter
and the value of that property refers to the DOM Element passed as an
argument. The DOM element is assigned a reference to the function object
and the result is a circular chain of references that goes; DOM Element
(with - onclick - property) -> function object (with - [[Scope]] -
property) -> scope chain -> Activation/Variable object (with - element -
property) -> DOM Element.

> You must be thinking of the nested functions such as:
>
> function SetEventHandler(element) {
> element.onclick = clickListener;
>
> function clickListener(event) {
> // make something
> }
> }


Are you thinking that there is a significant difference between the two
when it comes to the IE memory leak issue?

> which indeed forms a rather nasty closure


It is a rather ordinary closure.

> on each call so it leaks: on
> any platform for any browser.


No, it leaks on IE, not all browsers share IE's difficulty in seeing
circular chains of reference as insignificant when they are isolated
from the rest of the system.

> This syntax still has its useful application for particular
> circumstances - but it should avoided as hell anywhere else.

<snip>

Your advice is worthless if you cannot tell when and why a closure is
being produced and when it is not. So no change there then.

Richard.



RobG 12-08-2006 12:49 AM

Re: Function declaration inside other function
 

Larax wrote:
> Thanks for your explanations, I could have ran into serious problems
> with the IE memory leak as I'm assigning quite a lot of event handlers
> that way.


You can mitigate the memory leak issues by storing references to the
elements that you've attached event handlers to, then removing them
when the unload event occurs. More work certainly, but may be a
cleaner result overall.

The memory leak really only becomes an issue where lots of pages invoke
it and a user opens many such pages without closing IE completely.
Design your application to minimize or nullify its effects by all
means, but don't be too frightened of it.

You might like to look at Richard Cornford's finalizer:

<URL: http://www.litotes.demon.co.uk/examp...finalizer.html >


Matt Kruse 12-08-2006 03:46 AM

Re: Function declaration inside other function
 
VK wrote:
> Matt Kruse wrote:
>> Be careful - the example above creates a memory leak in IE.

> No, it does not.


And you question why people think your posts are dangerous to those who wish
to learn?

It will leak.
It's a classic example of the leak scenario.
In fact, one of the very _simplest_ examples of the leak scenario.

"Better to keep your mouth closed and be thought a fool than to open it and
remove all doubt"

Too late.

--
Matt Kruse
http://www.JavascriptToolbox.com
http://www.AjaxToolbox.com



VK 12-08-2006 11:09 AM

Re: Function declaration inside other function
 
Matt Kruse wrote:
> And you question why people think your posts are dangerous to those who wish
> to learn?


A *single* Usenet post of any author is always a dangerous source to
learn anything: unless someone is playing God and others accept this
role. Comments and corrections ("shared knowledge") give the Usenet
it's power.

> It will leak.
> It's a classic example of the leak scenario.
> In fact, one of the very _simplest_ examples of the leak scenario.


Yep, my mistake. I missed that the named function arguments will
participate in closure as well. Funny anough it is mentioned in the
very MSDN article I have linked:
<http://msdn.microsoft.com/library/default.asp?url=/library/en-us/IETechCol/dnwebgen/ie_leak_patterns.asp>
but somehow I overlooked it.
As a weak excuse (because any of my excuses is weak, is it? :-) I can
say that in-house we are using only only i) 100% guaranteed
non-closures over function augmentation or ii) 100% guaranteed closures
(when needed) so skipping on any even a bit doubtful cases. This way
"closure or not" studies were not conducted for all possible cases.

"Don't use closures unless you really need closure semantics."
(Eric Lippert)

But as this question touched anyway, I'm wandering now about the
situation w/o named arguments:

<html>
<head>
<title>Demo</title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<script type="text/javascript">

function SetEventHandler() {
if (typeof arguments[0] == 'object') {
arguments[0].onclick = function() {
window.alert(this.tagName);
};
}
}

function init() {
SetEventHandler(document.getElementsByTagName('p')[0]);
}

window.onload = init;
</script>
</head>
<body>
<h1>Demo</h1>
<p>Click me</p>
</body>
</html>


Does it mean that P sent as anonymous argument is still retained
somewhere in Activation/whatchamacall so forming a circular reference?

> "Better to keep your mouth closed and be thought a fool than to open it and
> remove all doubt"


Yawn.

I "open my mouth" not to be the smartest one on the block but to say
what I think on the question.

Sometimes (very often as you state) it allows to *others* to show up as
the smartest one around: so I see no reason to complain :-)

Sometimes it allows to break age old myths like "prototypes are used
for defaulting instance variables" (anonymous quote).

Yawn... I'm back to sleep now...


Richard Cornford 12-08-2006 11:53 AM

Re: Function declaration inside other function
 
VK wrote:
> Matt Kruse wrote:
>> And you question why people think your posts are dangerous to those
>> who wish to learn?

>
> A *single* Usenet post of any author is always a dangerous source to
> learn anything: unless someone is playing God and others accept this
> role.


Everyone gets to judge for themselves how worth listening to any
individual is.

> Comments and corrections ("shared knowledge") give the Usenet
> it's power.


Your tendency to disregard corrections and explanations tends to act
against any "power" of Usenet, as it wastes considerable time in
requiring your being re-corrected in order that the victims of your
deranged ramblings do not suffer from taking you seriously.

> > It will leak.
> > It's a classic example of the leak scenario.
> > In fact, one of the very _simplest_ examples of the leak scenario.

>
> Yep, my mistake. I missed that the named function arguments will
> participate in closure as well.


How many times has variable instantiation been explained to you now? I
have done so at least twice and I know others have as well.

> Funny anough it is mentioned in the
> very MSDN article I have linked:
> <http://msdn.microsoft.com/library/default.asp?url=/library/en-us/IETechCol/dnwebgen/ie_leak_patterns.asp>
> but somehow I overlooked it.


Even if you had read it you probably would not have understood.

> As a weak excuse (because any of my excuses is weak, is it? :-) I can
> say that in-house we are using only only i) 100% guaranteed
> non-closures over function augmentation or ii) 100% guaranteed closures
> (when needed) so skipping on any even a bit doubtful cases.

<snip>

Nonsense. In order to control when to use closures and when not to it
is necessary to understand how and when they are created. You have
repeatedly demonstrated, here and in previous code you have posted to
the group, that you have little comprehension of what is going on in
executing javascript, and certainly don't understand closures.

However, as you could not be employed in any organisation that also
employed real programmers (as your incompetence would then be pointed
out to however was in charge) talking of "in-house" doesn't mean much,
and certainly is not something that will be taken as guidance by the
rational.

> But as this question touched anyway, I'm wandering now about the
> situation w/o named arguments:


There is no need to wonder, understand javascript and you will know.

<snip>
> function SetEventHandler() {
> if (typeof arguments[0] == 'object') {
> arguments[0].onclick = function() {
> window.alert(this.tagName);
> };
> }
> }

<snip>

> Does it mean that P sent as anonymous argument is still retained
> somewhere in Activation/whatchamacall so forming a circular
> reference?


Yes of course it is; - arguments - is a property of the
Activation/Variable object and the object referred to by - arguments -
has a - 0 - property that is a reference to the DOM Element.

>> "Better to keep your mouth closed and be thought a fool than to open
>> it and remove all doubt"

>
> Yawn.
>
> I "open my mouth" not to be the smartest one on the block but to say
> what I think on the question.


But what you think is not informed by any understanding of the subject.
Indeed it is mostly a deranged fantasy with little connection to the
real world.

> Sometimes (very often as you state) it allows to *others* to show up as
> the smartest one around: so I see no reason to complain :-)


There is no need for a "smartest one around" competition in correcting
you, you know so little about javascript that even relative novices
understand more than you. You do appear to be yourself competing in a
'most incapable of learning' competition, as it takes a considerable
effort on the part of many individuals to get you to take any tiny step
towards a better understanding of javascript.

> Sometimes it allows to break age old myths like "prototypes are used
> for defaulting instance variables" (anonymous quote).

<snip>

Why anonymous? That is a true statement. That you think of it as a
"myth" is a product of your failure to comprehend javascript, that you
think you may have broken that "myth" is a product of your
self-delusion. You will learn more, and more quickly, if you do not
take the position that you are right and everyone else is wrong. The
result of that attitude has already made you look ridiculous.

You open your mouth and again leave everyone in no doubt that you are a
fool.

Richard.



All times are GMT. The time now is 09:37 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.