Function declaration inside other function

L

Larax

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
 
M

Matt Kruse

Larax said:
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.
 
R

Richard Cornford

Larax said:
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.
 
L

Larax

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
 
V

VK


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:
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>
 
R

Richard Cornford

VK said:
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.
 
R

RobG

Larax said:
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/example_scripts/finalizer.html >
 
M

Matt Kruse

VK said:
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.
 
V

VK

Matt said:
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/d...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...
 
R

Richard Cornford

VK said:
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.
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/d...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.

function SetEventHandler() {
if (typeof arguments[0] == 'object') {
arguments[0].onclick = function() {
window.alert(this.tagName);
};
}
}
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.
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.
 
V

VK

Richard said:
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.

fricking cold (43F), clouds, someone's called your yesterday article
"deranged ramblings". What more anyone would want for a really good
morning? :)

function SetEventHandler() {
if (typeof arguments[0] == 'object') {
arguments[0].onclick = function() {
window.alert(this.tagName);
};
}
}
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.

Very interesting. In such case it would be better called "The Closure's
Curse" :)
Just anouther proof of how smart I was by staying away from the fashion
and by going from stay-alone functions right onto function
augmentation.

So effectively in order to i) assign an individual method to an object
withing a function AND ii) do not form a circular reference in
JavaScript the only two ways are:

1) by using Function constructor (because it evaluates all its
components into string representations before storing them):

function SetEventHandler(element) {
element.onclick = new Function("evt",
"window.alert(this.tagName);".concat(
"try {window.alert(element);}",
"catch(e) {window.alert(e.message);}"));
}

2) by using object cloning as I do sometimes in my "all time best"
function augmentation schema:

function SetEventHandler(element) {
element.onclick = new Object(SetEventHandler.clickListener);
}
SetEventHandler.clickListener = function() {
// make something
}

Did I miss any other opportunity?

///////////////////////
<snip>

Why anonymous? That is a true statement.

In this case I must be missing the meaning you put into "defaulting
instance variables". To my humble mind it means "creating default
instance members". If I'm correct in my translation then you are
obviously wrong. If my translation is wrong then could you use a lesser
ambiguous statement?

Say in a case like:

function MyObject(arg) {
this.member1 = arg || 'foo';
this.member2 = 'bar';
}

var obj1 = new MyObject('foobar');
var obj2 = new MyObject;

MyObject constructor is "defaulting instance variables" for obj1 and
obj2 (via initialization arguments and via default values pre-coded
into constructor). Each object instance has it's own set of members
initialized with default values.

Bu in case like:

function MyObject(arg) {
this.member2 = arg || 'bar';
}
MyObject.prototype.member1 = 'foo';

var obj1 = new MyObject('foobar');
var obj2 = new MyObject;

there is not any "defaulting instance variable" for member1, because
neither obj1 nor obj2 do have this member. They can find it though in
their prototype chain if we ask them to do so: but neither one of them
has an individual property called "member1".

This way "defaulting instance variable" in application to the second
case sounds (to me at least) as not a really convenient term.

"prototype is used to include given static member into lookup chain of
all instances produced by the given function-constructor"

The latter definition is longer, but IMO here is one of cases when
shorter doesn't mean better.
 
D

Dr J R Stockton

In comp.lang.javascript message
Fri said:
A *single* Usenet post of any author is always a dangerous source to
learn anything:

Untrue.

I could post, in a few lines, assuming only a knowledge of elementary
algebra and physics, a proof of the little-known fact that the Roche
Period depends inversely on the square root of the density of the
spherical secondary, and depends on no other variable.

Anyone with the said elementary knowledge could learn that from the
article, but might never have considered doing the work himself.
 
R

Richard Cornford

VK said:
Richard said:
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.

fricking cold (43F), clouds, someone's called your
yesterday article "deranged ramblings". What more
anyone would want for a really good morning? :)
function SetEventHandler() {
if (typeof arguments[0] == 'object') {
arguments[0].onclick = function() {
window.alert(this.tagName);
};
}
}
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.

Very interesting.

Not really, you should have known that properties of the - arguments -
object have the values of arguments passed to the function when called,
and that the arguments object must be property of the
Activation/Variable object with the name 'arguments' in order to be able
to use the Identifier - arguments - to refer to that object within a
function. You should not be claiming to have spent ten years writing
javascript and still need to ask the question, or be surprised by the
answer.
In such case it would be better called "The
Closure's Curse" :)

Why? Nothing has changed just because you have eventually become aware
of another truth about javascript.
Just anouther proof of how smart I was by staying away
from the fashion and by going from stay-alone functions
right onto function augmentation.

1. You have not, in any sense, avoided creating closures (the
code you have posted to this group over the last year
demonstrates that beyond question), all you have done is
remained sufficiently ignorant of javascript to know when
and where you were forming closures.

2. It makes no sense to try to avoid a language feature out of
fear and ignorance. Once understood people can make informed
design decisions about the use, benefits and drawbacks of
using closures.

3. Your code (and strategies you have often recommended to
others) often explicitly creates circular chains of reference
including DOM nodes, so even if you were not creating
closures without knowing it you would still not be avoiding
the memory leak issue.
So effectively in order to i) assign an individual method
to an object withing a function AND ii) do not form a
circular reference in JavaScript the only two ways are:

You are about to demonstrate you ignorance agin.
1) by using Function constructor (because it evaluates
all its components into string representations before
storing them):

The use of the function constructor does not form closures because the
[[Scope]] property of the resulting function objects only has the global
object on the scope chain referred to.

2) by using object cloning as I do sometimes in my "all
time best" function augmentation schema:

function SetEventHandler(element) {
element.onclick = new Object(SetEventHandler.clickListener);
}

Why have you wrapped the reference to - SetEventHandler.clickListener -
in a use of the Object constructor? All that will do is return the
argument object. It is an indirect, wasteful, worthless and pointless
alternative to writing just:-

element.onclick = SetEventHandler.clickListener;

Another example of your doing something poorly for no justifiable reason
beyond your usual 'because I can, and it "works"'.

Ah, you wrote "object cloning". You actually think this might result in
differing function objects being assigned to - onclick - properties. It
will not. There is no "cloning" happening here, just the assigning of
potentially many references to the same function object to different
element's onclick properties.

You call this your "'all time best' function augmentation schema" and
you don't even know what the code you have written actually does.

SetEventHandler.clickListener = function() {
// make something
}

Did I miss any other opportunity?

Of course you did. You missed the obvious and simple (which appears to
be a characteristic of your mental process). If the issue follows from
circular chains of reference then the solution is to remove any one
reference and the result will not be circular, and so will not provoke
the issue. In the case of the original function as simple last line of:-

element = null;

- stops the Activation/Variable object from referring to the DOM Element
and so breaks the circle. The - onclick - handler does not need that -
element - reference as it can refer to its DOM Element with the -
this - keyword, or it can get that reference as a property of the event
object.

///////////////////////


In this case I must be missing the meaning you put into
"defaulting instance variables".

Of course you are. You repeatedly demonstrate very little valid
comprehension of OO concepts. You may like to make a lot of noise on the
subject but you are not fooling anyone.
To my humble mind it means "creating default
instance members".

Yes, you usually fail to comprehend the distinction between a concept
and its specific manifestation.

"Instance variable" is a term for a general concept in OO programming.
If I'm correct in my translation then you are
obviously wrong.

And pigs may fly.
If my translation is wrong then could you use a
lesser ambiguous statement?

Say in a case like:

function MyObject(arg) {
this.member1 = arg || 'foo';
this.member2 = 'bar';
}

var obj1 = new MyObject('foobar');
var obj2 = new MyObject;

MyObject constructor is "defaulting instance variables" for
obj1 and obj2 (via initialization arguments and via default
values pre-coded into constructor). Each object instance
has it's own set of members initialized with default values.

The concept of an "instance variable" does not require that each object
instance actually have the property in question, only that treating them
as if they had the property was viable. If they inherit the property
through their prototype chain then they can be treated as if they had
the property (in that the property can be both read and set (or methods
called as methods).

Fixating on the objects themselves having all of their own properties,
rather than inheriting them, will result in really poor javascript
authoring. It is just not required in javascript to satisfy OO concepts,
and fully exploiting prototype inheritance can greatly increase the
efficiency and clarity of javascript code.
Bu in case like:

function MyObject(arg) {
this.member2 = arg || 'bar';
}
MyObject.prototype.member1 = 'foo';

var obj1 = new MyObject('foobar');
var obj2 = new MyObject;

there is not any "defaulting instance variable" for
member1,

Yes there is. If you read - obj2.member1 -or obj1.member1 - you will get
the default value of 'foo', and you will keep getting that value until
you assign to the - member1 - property of each object. That is
"defaulting an instance variable" in every practical sense.
because neither obj1 nor obj2 do have this member.

In a language using prototype inheritance the object instance is not
just the object itself, it is the object plus its prototype chain.
Fixating on the object itself is failing to see the nature of the
objects in javascript.
They can find it though in
their prototype chain if we ask them to do so:

That is the nature of javascript object instances; they behave as if
they have the properties of their prototypes when they don't have them
themselves. Thus you can extend a 'class' that has one of its instances
assigned as a prototype without having to do any more than implement the
extending features.
but neither one of them
has an individual property called "member1".

They behave as if they have the property without the need to actually
have it. that is a good thing.
This way "defaulting instance variable" in application
to the second case sounds (to me at least) as not a
really convenient term.

Your use of language and terminology is generally perverse. It tends to
leave you wallowing in misconception.
"prototype is used to include given static member into
lookup chain of all instances produced by the given
function-constructor"

The concept of "static member" does not apply to the properties of the
prototype, but then you don't understand that concept either. And the
specifics of the prototype chain resolution of property names are
inappropriate when talking about general OO concepts. It is only
necessary at the stage of understanding how those concepts may be
implemented with javascript.
The latter definition is longer, but IMO here is one of
cases when shorter doesn't mean better.

It is nonsense, so shorter or longer is irrelevant.

Richard.
 
V

VK

Richard said:
You missed the obvious and simple (which appears to
be a characteristic of your mental process). If the issue follows from
circular chains of reference then the solution is to remove any one
reference and the result will not be circular, and so will not provoke
the issue. In the case of the original function as simple last line of:-

element = null;

- stops the Activation/Variable object from referring to the DOM Element
and so breaks the circle.

The situation is much more complicated as I see it (would be glad to be
corrected).
In fact each time you are "wrapping" the entire constructor context
into each individual method: with all constructor's arguments and
intermediary variables. It is as if with each new TV-Set made, you
would send as well the iron, leftovers of wires and your empty lunch
bag. In the sample below [data] string - sent as constructor argument -
presumed to be something big and useful (say XML data to build the
relevant DOM branch). It was used in the constructor and never
addressed ever after: *but* in fact we are duplicating this (say 50Kb -
1Mb big) string in the "parasite context" of *each* onclick handler.
And it has nothing to do with IE specifics: this applies to any
ECMAScript-compliant engine.

<script type="text/javascript">

var JSxDOM = null;

function F(element, data) {
element.onclick = function() {
window.alert(data);
}
}

function init() {
JSxDOM = new F(document.getElementsByTagName('h1')[0],
'A very long string'
);
}

window.onload = init;
</script>

This way on each invocation it seems we have to nullify first the
arguments object itself:
arguments = null;
// because something nasty can be beyond
// the range of named function arguments,
// say F(arg1, arg2, null, null, bigSurprise)
and then we have to individually shoot down each named argument:
element = null;
data = null;
and then (as we don't have some enumerable Local object) we may also
have to individually shoot down the most "nasty" local (intermediary)
variables if we had to create any.

This still will be leaking at least for the size of an object reverence
(because we cannot "kill" the Activation object itself, only clean up
its members) but this is already a negligible detail.

This way the full code for the sample above would be something like:

function F(element, data) {
// do with data
element.onclick = function() {
window.alert(data);
}
arguments = null;
element = null;
data = null;
}

So effectively we have to substitute JavaScript's automated memory
management with some highly tedious manual "half-destructors".

In such case indeed using each closure is just like "calling Satan to
do the job": only if you really believe to retain your full control and
only if truly private instance variables are absolutely needed.

To avoid any possible "probe effect" (data retained because of generic
closure mechanics? or because it's used in onclick handler and this is
why it's forming a closure?) I changed the test.
You have to have Microsoft Script Debugger
<http://en.wikipedia.org/wiki/Microsoft_Script_Debugger> for IE
installed and enabled. You may use any other debugger with breakpoints
and runtime memory access: but you have to replace [debugger] operator
then.
Here is the code, below it is the screenshot after Debug.write(data)
executed.

///////////

<html>
<head>
<title>Demo</title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<script type="text/javascript">
function F(element, data) {
element.onclick = function() {
debugger;
}
}
function init() {
var JSxDOM = new F(document.getElementsByTagName('h1')[0],
'A very long XML string'
);
}
window.onload = init;
</script>
</head>
<body>
<h1>Demo</h1>
</body>
</html>

///////////

<http://www.geocities.com/schools_ring/closure.gif>

So am I right or am I not right? If I'm right then you guys just real
a**holes: because it is something to scream and squeal each time seeing
anything like
function f() {... this.m = function(){... }

Instead one is using singletons on everything "because I like it this
way better", another is calling to abandone [new] "because it is not
needed anymore", other is perpetually busy by measuring the exact
negative value of my IQ. I feel myself the least guilty here because I
simply never used function-in-function unless sometimes for curiosity
of "what if..." so I sincerely did not know the exact picture.
 
R

Richard Cornford

Oops... I meant new Function, sorry.

So you are not sufficiently familiar with your "'all time best' function
augmentation schema" to write an example of it at the first attempt (or
apparently the second).

Substituting - new Function - for - new Object - will take code that
"works", in the very broadest sense, and turn it into code that does
nothing useful at all.
http://groups.google.com/group/comp.lang.javascript/msg/fc4bd916619ef0c9
<snip>

I have seen it, and it is a masterpiece of obtuse and stupid javascript
authoring, with the bug that will result in implementation dependent
failure just the cherry on the top.

Richard.
 
R

Richard Cornford

VK said:
The situation is much more complicated as I see it (would be
glad to be corrected).

Yes, understudying and perceiving complexity is certainly an area where
you have considerable difficulty. You write code that is orders of
magnitude more complex than it needs to be and then see insurmountable
complexity in simple structures of references.
In fact each time you are "wrapping" the entire constructor
context into each individual method:

There is not constructor (and so no "constructor context", whatever that
is intended to refer to) in the original function. You have just made
another of those leaps of irrational association that tends to leave you
whittering on about the irrelevant and missing the meat of the real
issues.
with all constructor's arguments and intermediary variables.
It is as if with each new TV-Set made, you would send as well
the iron, leftovers of wires and your empty lunch bag.

A function that forms a closure is associated with the environment it
was created within for the duration of its existence. That is the point
of closures.
In the sample below [data] string - sent as constructor
argument - presumed to be something big and useful (say
XML data to build the relevant DOM branch). It was used
in the constructor and never addressed ever after:
*but* in fact we are duplicating this (say 50Kb
- 1Mb big) string

Says who? Javascript string primitives are immutable so the difference
between an implementation creating a copy of a string primitive to pass
to a function and an implementation passing a reference to a single
string primitive representation is undetectable, and as the latter would
be considerably more efficient it is likely to be the chosen path in
reality.
in the "parasite context"

You just love to make this terminology up off the top of your head. It
doesn't do you any good in the long run as it just leaves you gibbering
away in some incomprehensible jargonees.
of *each* onclick handler.
And it has nothing to do with IE specifics: this applies
to any ECMAScript-compliant engine.

As you have no ides what an ECMAScript-compliant engine would be you
really should not attempt to pontificate on the subject.

The issue being considered here is IE specific. If a circular chain of
references includes a COM object (including any ActiveX object or DOM
Node) then the applicable garbage collectors are incapable of freeing
the memory used by all the objects in that structure and that memory
will remain occupied until the browser is closed down.

Other browser are quite capable of cleaning up their memory as they
operate, regardless of chains of reference or the types of objects that
may be involved in those chains.

It may be the case that if you have a 1 MB string in a position where it
can be referenced by executing code then you have 1 MB of memory
consumed in accommodating it, but that is just a common software memory
footprint issue (and not a particularly concerning one considering the
low cost of memory and the amounts commonly available in computers these
days).

Even in IE, if you haven't arranged for an object that is part of a
circular chain of references that includes a COM object to refer to your
1MB string then it will be garbage collected after it becomes
inaccessible and the memory it occupies will be freed.
<script type="text/javascript">

var JSxDOM = null;

function F(element, data) {
element.onclick = function() {
window.alert(data);
}
}

function init() {
JSxDOM = new F(document.getElementsByTagName('h1')[0],
'A very long string'
);
}

window.onload = init;
</script>

This way on each invocation it seems we have to nullify
first the arguments object itself:
arguments = null;
// because something nasty can be beyond
// the range of named function arguments,

Computer programming really is a closed book to you. Why would someone
pass an object references as an argument to a function that would never
do anything with that argument. I know that you program by mystical
incantation and coincidence and so might so something that stupid (and
point out that it "works" when asked for a expiation of why) but in real
programming the programmer knows why they are writing the code they
write and so they do not randomly add undocumented arguments to function
calls in the hope that the may do something useful.
// say F(arg1, arg2, null, null, bigSurprise)
and then we have to individually shoot down each named argument:
element = null;
data = null;
and then (as we don't have some enumerable Local object) we
may also have to individually shoot down the most "nasty"
local (intermediary) variables if we had to create any.

Nonsense. The issue is the circular chain of references including the
COM object. Break the circle and IE will have no trouble garbage
collecting the rest as soon as it is finished with.

If you really have passed a 1MB string into the argument and the closure
is expected to be long lived, and you thing total memory consumption on
the client is likely to be an issue such that 1MB here or there will
make a difference, then by all means assign null to the now redundant -
data - parameter. Generally the memory consumed by the COM object will
be far in excess of anything else involved in the structure.
This still will be leaking at least for the size of an
object reverence (because we cannot "kill" the Activation
object itself, only clean up its members) but this is already
a negligible detail.

It is only a leak if the garbage collector cannot clean up the memory,
and that will not be the case as soon as the - element - parameter stops
referring to the COM object.
This way the full code for the sample above would be something
like:

function F(element, data) {
// do with data
element.onclick = function() {
window.alert(data);
}
arguments = null;
element = null;
data = null;
}

So effectively we have to substitute JavaScript's automated
memory management with some highly tedious manual
"half-destructors".

There is a known issue with IE browsers that should be understood and
addressed by people coding for them. Your knee-jerk flight to absurdity
helps nobody (except to see how unknowledgeable and irrational your
are). The situation is simple-

Circular chains of reference including COM object cause an issue. You
address that issue by:-

1. Not creating circular chains of reference that include COM object.

- or:-

2. Breaking any circular chains of reference that include COM objects
when they are no longer needed.

There is no need to start building some elaborate ceremony of
incantations and sacrificing to the gods around this.
In such case indeed using each closure is just like "calling
Satan to do the job": only if you really believe to retain
your full control and only if truly private instance variables
are absolutely needed.

If you prefer to throw up your hands in horror and run screaming into to
the woods then that is up to you. Programmers will get by with
understanding the mechanisms they are using and programming them to do
what is needed.
To avoid any possible "probe effect"

More 'off the top of your head' jargon?
(data retained because of generic closure mechanics? or
because it's used in onclick handler and this is
why it's forming a closure?)

If you are trying to explain the jargon you fabricate the leas you
should do is attempt to use coherent sentences.
I changed the test.
You have to have Microsoft Script Debugger
<http://en.wikipedia.org/wiki/Microsoft_Script_Debugger> for IE
installed and enabled. You may use any other debugger with
breakpoints and runtime memory access: but you have to replace
[debugger] operator then.
Here is the code, below it is the screenshot after
Debug.write(data) executed.

///////////

<html>
<head>
<title>Demo</title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<script type="text/javascript">
function F(element, data) {
element.onclick = function() {
debugger;
}
}
function init() {
var JSxDOM = new F(document.getElementsByTagName('h1')[0],
'A very long XML string'
);
}
window.onload = init;
</script>
</head>
<body>
<h1>Demo</h1>
</body>
</html>

///////////

http://www.geocities.com/schools_ring/closure.gif

And your pont is?

Why do you do this? You have been repeatedly told that if you do not
state whatever it is that these 'demonstrations' are supposed to be
demonstrating nobody will ever be able to tell you why they demonstrate
nothing of the sort and which of your misconceptions are fooling you
into thinking they do.
So am I right or am I not right?

Right about what? If you cannot state what it is you think you might be
right about you cannot be told why you are wrong. You will be wrong, but
that is because you are VK and you are delusional.
If I'm right then you guys just real
a**holes:

Don't worry, you will be wrong, and told why as soon as you explain
whatever it is you think you are right about.
because it is something to scream and squeal each time
seeing anything like
function f() {... this.m = function(){... }

Instead one is using singletons on everything "because I like
it this way better",

You are getting incoherent again.
another is calling to abandone [new] "because it is not
needed anymore", other is perpetually busy by measuring the exact
negative value of my IQ.

Pure gibberish! Insanity on your part really is the best explanation for
you propensity for starting of just about making sense and then
degenerating into this incomprehensible babble.
I feel myself the least guilty here because I simply
never used function-in-function unless sometimes for
curiosity of "what if..."

Bullshit. Remember that the code you post is in the archives and that
record show many occasions where you uses inner functions, form closures
(including memory leaking closures) and label such constructs are you
normal programming style, recommending it to others (in disregard of the
constant stream of criticism it has attracted for its obtuse, inept and
often stupid use of the language).
so I sincerely did not know the exact picture.

No you don't, and until you appreciate how very little you do understand
about javascript and how utterly wrong most of your perceptions are, and
go back an start learning it over, you never will.

Richard.
 
V

VK

Richard said:
A function that forms a closure is associated with the environment it
was created within for the duration of its existence. That is the point
of closures.

Including [arguments] object and named function arguments. So you knew
it all these years, but you found much more important to teach using
"type" attribute instead of "language"?
From the other side you might just do not fully realize the amount of
the potential sh**. Reading once over
<http://blogs.msdn.com/ericlippert/archive/2003/09/17/53028.aspx> I see
that Eric Lippert did not realize it. Everyone is just hypnotized by
that "DOM circular reference in IE" (further "DCR") as it's some the
most crucial and nearly the only one matter.
DCR is a rather small (in comparison) issue not connected to closures.
Yes, closures are (up to date) the main source of it, but DCR neither
needs closures nor depends on them.
In the sample below [data] string - sent as constructor
argument - presumed to be something big and useful (say
XML data to build the relevant DOM branch). It was used
in the constructor and never addressed ever after:
*but* in fact we are duplicating this (say 50Kb
- 1Mb big) string

Says who? Javascript string primitives are immutable so the difference
between an implementation creating a copy of a string primitive to pass
to a function and an implementation passing a reference to a single
string primitive representation is undetectable, and as the latter would
be considerably more efficient it is likely to be the chosen path in
reality.

What a holly word are you talking about? Inner function forms a closure
around the *current* execution context of the outer function.
Everything in this context - including arguments - will be preserved
*every time*. You can send the same string as an argument 100 times,
and 100 copies of this string will be created.

The below sample are targeted for people i) having IE / Microsoft
Script Debugger and ii) knowing to type in Debug.write(data) into
console. To launch the debugger, you have to click on any of two H2
elements.

IMO other debuggers for other UA's are still rather weak for serious
studies. If I'm wrong and you know an equivalent of JScript debugger;
so later study the momentary memory state (say on Venkman) then go
ahead. I simply didn't know of any so in the second sample (for
Firefox) I used eval() with exception trigger.

///////////////
<html>
<head>
<title>Untitled Document</title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">

<!-- This script uses JScript and Microsoft
Script Debugger specific statements.
It will fail on any UA other than Iinternet Explorer
with Microsoft Script Debugger installed. -->

<script type="text/Jscript">

function F(element, data) {
element.onclick = function() {
window.alert(this.innerHTML);
debugger;
}
element = null;
}

function init() {
var h2 = document.body.getElementsByTagName('h2');
F(h2[0], '100Kb string');
F(h2[1], 'another 100Kb string');
window.setTimeout(CollectGarbage, 100);
}

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

///////////////

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

function F(element, data) {
element.onclick = function() {
window.alert(this.innerHTML);
eval("try{throw new Error(data)}catch(e){alert(e.message)}");
}
element = null;
}

function init() {
var h2 = document.body.getElementsByTagName('h2');
F(h2[0], '100Kb string');
F(h2[1], 'another 100Kb string');
}

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

<body>
<h1>Demo</h1>
<h2>Click me 1</h2>
<h2>Click me 2</h2>
</body>
The issue being considered here is IE specific. If a circular chain of
references includes a COM object (including any ActiveX object or DOM
Node) then the applicable garbage collectors are incapable of freeing
the memory used by all the objects in that structure and that memory
will remain occupied until the browser is closed down.

What does this agglomeration of words mean? What does COM object have
to do with it? (unless it's a typo instead of "DOM").
Automation-related memory leaking over COM objects is all another
separate issue. Try to understand and disassemble in your mind: there
are three (3) main memory leaking situations:
1) Closures formed by inner functions: universally. This one we are
talking about now.
2) "DOM circular reference" : Internet Explorer specific.
3) COM instances leaking: Windows platform specific, any UA capable to
use automation (IE first of course, UAs with GeckoActiveXObject support
next).

These are all different situations caused by all different reasons.
Let's us talk one at the time, OK?
Don't worry, you will be wrong, and told why as soon as you explain
whatever it is you think you are right about.

Consider the two posted test cases above as an IQ test. If you get at
least a rough idea of what am I talking about, your IQ is high enough
to keep the discussion.
 
R

Richard Cornford

VK said:
Richard said:
A function that forms a closure is associated with the
environment it was created within for the duration of its
existence. That is the point of closures.

Including [arguments] object and named function arguments.
So you knew it all these years,

As did everyone else.
but you found much more important to teach using
"type" attribute instead of "language"?

<quote cite="http://jibbering.com/faq/faq_notes/closures.html"
Javascript Closures
....
Then the process of "variable instantiation" takes place using an object
that ECMA 262 refers to as the "Variable" object. However, the
Activation object is used as the Variable object (note this, it is
important: they are the same object). Named properties of the Variable
object are created for each of the function's formal parameters, and if
arguments to the function call correspond with those parameters the
values of those arguments are assigned to the properties (otherwise the
assigned value is undefined). Inner function definitions are used to
create function objects which are assigned to properties of the Variable
object with names that correspond to the function name used in the
function declaration. The last stage of variable instantiation is to
create named properties of the Variable object that correspond with all
the local variables declared within the function.

The properties created on the Variable object that correspond with
declared local variables are initially assigned undefined values during
variable instantiation, the actual initialisation of local variables
does not happen until the evaluation of the corresponding assignment
expressions during the execution of the function body code.

It is the fact that the Activation object, with its arguments property,
and the Variable object, with named properties corresponding with
function local variables, are the same object, that allows the
identifier arguments to be treated as if it was a function local
variable.
....
Written by Richard Cornford. March 2004.
....
</quote>

You have been refereed to that document many times by now. It is not my
fault if you have not read it or could not understand it.

In writing and publishing that article I have probably done more to
promote a sound, technical and comprehensive understanding of closures
in javascript than any other individual.
amount of the potential sh**. Reading once over
http://blogs.msdn.com/ericlippert/archive/2003/09/17/53028.aspx
I see that Eric Lippert did not realize it. Everyone is just
hypnotized by that "DOM circular reference in IE" (further
"DCR") as it's some the most crucial and nearly the only one
matter. DCR is a rather small (in comparison) issue not
connected to closures. Yes, closures are (up to date) the
main source of it, but DCR neither needs closures nor
depends on them.

Have I not pointed out to you on numerous occasions that your habit of
attaching expandos to DOM nodes that refer to your JS object and giving
those JS objects properties that refer to the DOM nodes provokes the IE
memory leak issue (without any closures, though you randomly add
worthless closures to the mix as well)? The issue is, and always has
been, the circular chins of reference including COM objects,
irrespective of how those chains are created.
In the sample below [data] string - sent as constructor
argument - presumed to be something big and useful (say
XML data to build the relevant DOM branch). It was used
in the constructor and never addressed ever after:
*but* in fact we are duplicating this (say 50Kb
- 1Mb big) string

Says who? Javascript string primitives are immutable so
the difference between an implementation creating a copy
of a string primitive to pass to a function and an
implementation passing a reference to a single string
primitive representation is undetectable, and as the
latter would be considerably more efficient it is likely
to be the chosen path in reality.

What a holly word are you talking about?

The significance of "duplicating this (say 50Kb - 1Mb big) string", and
whether any actual duplication takes place.
Inner function forms a closure around the *current*
execution context of the outer function.

No, the execution context is not part of the closure. The closure is
with the Activation/Variable object at the top of the scope chain
referred to by the function's internal [[Scope]] property.
Everything in this context - including arguments - will
be preserved *every time*. You can send the same string
as an argument 100 times, and 100 copies of this string
will be created.

Maybe 100 copies will be created, maybe not. My point is that your
script cannot tell and when your script cannot tell the implementation
is free to optimise, and as string primitives are immutable the
difference between two strings holding the same character sequence and
two references to a single representation of the string is insignificant
(has no practical consequences). As the latter allows for less memory
consumption and quicker code execution optimising string primates into
references to fixed string representations will tend to be the preferred
choice in implementations.

Let me show you, and at the same time give you a demonstration of how
the rational set about demonstrating things.

First it is necessary to state what it is that is being demonstrated
(omitting this step is one of the main reasons you never manage to
demonstrate anything, make yourself look a fool in trying, and don't
manage to learn anything from your efforts). What is being demonstrated
is that in reality it is not necessary for a javascript implementation
to actually copy any string primitive value, and because it is not
necessary many (if not all) of them don't do so.

The next step is to explain how this is going to be demonstrated. The
assertion here is that passing a string primitive as the argument to a
function call will result in the string primitive being copied for use
within the function. Thus we will be creating a very big string
(10,000,000 characters, which is 20MB minim at 16 bits per character)
and then passing that string primitive as an argument to a function call
(so that if it is going to be copied it will be copied at that point).
Then, within the function we are going to append that string value to a
global Array so that it will not be garbage collected. We are going to
do this many times.

We will contrast this with appending the null value to the array as many
times as we appended 'copies' of the string primitive. This will show
the nature of the increase in memory use that follows from extending the
storage capacity of an Array.

The next step is to state how the demonstration will demonstrate what it
is to show:-

In principle, if the string primitives are copied the difference in the
memory increase resulting from assigning null values to the array and
the increase resulting from assigning 'copies' of the string primitive
will be the memory occupied by the copies of the character data. And
since the strings are 20 MB that difference should be readily evident in
the results.


The next step in the demonstration is the code that can then be used by
others to reproduce the effects and make the pint for themselves (or
examined to expose flaws in the experimental process, so long as the
reader knows what it is that the code is supposed to demonstrate):-

<html>
<head>
<title></title>
<script type="text/javascript">
function largeText(len, s) {
if (!s) s = '0123456789';
var a = [];
for(var i=len;i--;) a.push(s);
return a.join('');
}

var bigString = largeText(1000000);
var storage = [];
var limit = 100000;

function addString(s) {
storage.push(s);
}
function addNulls(){
storage.push(null);
}

function doStringWork(){
alert('Record starting system memory consumption.');
for(var c = 0;c < limit;++c){
addString(bigString);
}
alert(
limit+' '+
bigString.length+
' character long string values added to array'
);
}
function doNoStringWork(){
alert('Record starting system memory consumption.');
for(var c = 0;c < limit;++c){
addNulls();
}
alert(limit+' null values added to array');
}
</script>
</head>

<body>
<input type="button" onclick="doStringWork()"
value="add strings to array"><br>
<input type="button" onclick="doNoStringWork()"
value="add nulls to array"><br>
<br>
<script type="text/javascript">
document.write('bigString.length = '+bigString.length)
</script>
</body>
</html>

And finally some explanation of how the code is to be used, what is seen
when it is used and what conclusions can be drawn from those
observations:-

When the page loads it creates a very big string primitive which it
assigns to the global variable - bigString -, the length of this string
primitive is document.written to the end of the page (10,00,00
characters).

Two buttons are provided on the page and clicking those buttons triggers
one of two functions. These two functions loop a number of times
determined by a global variable called - limit - and assigned the value
100,000. Thus whatever these two functions do they do it one hundred
thousand times.

The first button triggers a function that calls a function called -
addString - inside the loop, and passes - bigString - as its argument.
Thus if - bigString - is copied when passed as an argument to a function
call it will be copied 100,000 times. The - addString - function pushes
its argument onto a global Array called - storage - so that it cannot be
garbage collected.

The second button triggered function calls a different function 100,000
times. This other function just pushes null onto the global - storage -
array.

Each of the button triggered functions puts up an alert before the loop,
to give the observer an opportunity to note the system memory use prior
to the loop being executed, and then pops up another alter after the
loop to signal when it is appropriate to take another reading of the
system memory used. these two readings allow the calculation of the
change in memory use resulting from the execution of the two loops.

If passing a string primitive as an argument to a function call really
does result in the copying of that string value then, given that the
string is 20 MB AND 100,000 copes would be made, then there should be a
very evident difference in the changes in memory consumption observed
following the use of each of the two buttons. This difference should
show the 'copying' of string primitives change the memory consumption by
around 2,000,000 MB (10,000,000 characters at two bytes each times
100,000 copies). A magnate of change that would be difficult to fail to
observe (as it should kill the OS).

Actually running the code on IE, Firefox and Opera does not show this
difference in memory consumption. Indeed the change in memory
consumption resulting from appending 100,000 null values to the array is
not significantly different from the change resulting from appending
100,000 string primitives.

The only reasonable conclusion that can be drawn from these observations
is that passing a string primitive as an argument to a function call
does not result in a copy of the character data in the string being
created in memory. At least in the browsers tested.

The below sample are targeted for people i) having IE /
Microsoft Script Debugger and ii) knowing to type in
Debug.write(data) into console. To launch the debugger,
you have to click on any of two H2 elements.

But what precisely is it you are trying to demonstrate? What point are
you trying to make?
IMO other debuggers for other UA's are still rather weak for
serious studies.

Your opinions are, as always, worthless.
If I'm wrong and you know an equivalent of JScript
debugger; so later study the momentary memory state
(say on Venkman) then go ahead. I simply didn't know
of any so in the second sample (for Firefox) I used
eval() with exception trigger.

The mechanism is irrelevant without any idea of what it is this code is
supposed to demonstrate. If you are trying to show that the value of -
data - formal parameter is available inside the event handling functions
then a simple - alert(data); - will show that. But as that parameter
value is expected to be available showing that it is available is rather
pointless.
///////////////
<html>
<head>
<title>Untitled Document</title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">

<!-- This script uses JScript and Microsoft
Script Debugger specific statements.
It will fail on any UA other than Iinternet Explorer
with Microsoft Script Debugger installed. -->

<script type="text/Jscript">

function F(element, data) {
element.onclick = function() {
window.alert(this.innerHTML);
debugger;
}
element = null;
}

function init() {
var h2 = document.body.getElementsByTagName('h2');
F(h2[0], '100Kb string');
F(h2[1], 'another 100Kb string');
window.setTimeout(CollectGarbage, 100);
}

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

///////////////

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

function F(element, data) {
element.onclick = function() {
window.alert(this.innerHTML);
eval("try{throw new Error(data)}catch(e){alert(e.message)}");
}
element = null;
}

function init() {
var h2 = document.body.getElementsByTagName('h2');
F(h2[0], '100Kb string');
F(h2[1], 'another 100Kb string');
}

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

<body>
<h1>Demo</h1>
<h2>Click me 1</h2>
<h2>Click me 2</h2>
</body>
</html>

So where its? What is the point you are trying to make?
What does this agglomeration of words mean?

It means exactly what it says.
What does COM object have to do with it?

It is including COM objects in circular chains of reference that provoke
IE's memory leak issue. How may ways of saying that do you think there
are?
(unless it's a typo instead of "DOM").

No. I wrote " COM object (including any ActiveX object or DOM Node)".
The issue applies to any object instantiated with - new ActiveXObject(
.... ); - in addition to DOM nodes (thus any COM object).
Automation-related memory leaking over COM objects is all
another separate issue.

And irrelevant to browser script authors.
Try to understand and disassemble in your mind: there
are three (3) main memory leaking situations:

Why don't you try reading and understanding what is written?
1) Closures formed by inner functions: universally. This
one we are talking about now.

Closures do not, of themselves, provoke memory leaks, even in IE.
2) "DOM circular reference" : Internet Explorer specific.

It is circular references that include COM object that provoke the
memory leak issue in IE.
3) COM instances leaking: Windows platform specific, any UA
capable to use automation (IE first of course, UAs with
GeckoActiveXObject support next).

The internal details of COM objects are irrelevant to the authors of
browser scripts who are interested in addressing the IE memory leak
issue.
These are all different situations caused by all different
reasons. Let's us talk one at the time, OK?

You could try, but you really will have to understand what I write in
order to do so.
Consider the two posted test cases above as an IQ test.

I consider their deficiencies as demonstrations of anything as an
indicator of yours (though wasn't it the week before last when you
announced surprise and pride in discovering that you were able to walk
and chew gum at the same time, or something similar, and perceived that
as an indicator or your IQ?

<quote cite="(e-mail address removed)">
P.S. OT: I'm an IQ monster :) At 5am I'm eating an open face turkey
sandwich by one hand and explaining JavaScript inheritance by other
hand. I'm ready to be an astranaute I guess :)
</quote>

).
If you get at least a rough idea of what am I talking
about, your IQ is high enough to keep the discussion.

You are not talking about anything. You have posted code that will
demonstrate javascript doing exactly what it is expected to do, and as
you have drawn no conclusions from, and attached no meaning to, that
there is no point being made above.

Richard.
 
M

Matt Kruse

Richard said:
In writing and publishing that article I have probably done more to
promote a sound, technical and comprehensive understanding of closures
in javascript than any other individual.

I agree, but what your article really needs is pictures! Seriously.

I explained closures to someone by drawing boxes on a whiteboard and it
seemed to help.
I then summarized it in text like this, to accompany your closure article:

Given this code:
----------------
var globalVar = 0;
function incrementor(count) {
var localFunc = function() {
globalVar += count;
return globalVar;
}
return localFunc;
}
var addTwo = incrementor(2);
alert(globalVar);
addTwo();
alert(globalVar);

A visual representation might look like this:
---------------------------------------------

+-[GLOBAL]-------------------------------------------------------+
| |
| var globalVar = 0; |
| |
| +-[INCREMENTOR]--------------------------------------------+ |
| | function incrementor(count) { | |
| | +-[ANONYMOUS]--------------------+ | |
| | var localFunc = | function() { |<=======+
| | | globalVar+=count; | | | #
| | | return globalVar; | | | #
| | | } | | | #
| | +--------------------------------+ | | #
| | return localfunc; | | #
| | } | | #
| +----------------------------------------------------------+ | #
| var addTwo = incrementor(2); // ===(addTwo is now one of these)==+
| alert(globalVar); |
| addTwo(); |
| alert(globalVar); |
+----------------------------------------------------------------+

Each time a function is entered, an Execution Context is created. These are
represented by a box in the diagram ([NAMES] are for ease of reference
only), which contain a function which is the Activation Object.

The Scope Chain of an Execution Context includes all the boxes it is
contained in when it is evaluated. A function inside an Execution Context
can "see" any variables that are defined in any box in its scope chain, and
when it tries to resolve an identifier, it checks each context from inner to
outer to see if the identifier is defined there. This is why the ANONYMOUS
Execution Context can refer to both the globalVar value which is held in the
GLOBAL Execution Context and the count value which is held in the
INCREMENTOR Execution Context.

The closure is created here when "addTwo" is defined by calling the
"incrementor" method. Internally, the "incrementor" method returns a
reference to a newly-created ANONYMOUS function, which gets assigned to the
"addTwo" property in the GLOBAL context. Even though the incrementor
function exits, a reference still exists to the ANONYMOUS execution context.
And in order for it to exist, its entire scope chain must exist. Otherwise,
the ANONYMOUS function wouldn't know how to resolve the value of "count".

Therefore, a closure is formed. The value of "count" in the incrementor
function is maintained for as long as the ANONYMOUS function exists. The
entire scope chain continues to exist even though the function has exited,
because it must be there for the inner function to execute.

[END]

Richard, I think a diagram like above would help people to understand the
concept better, since many programmers are visual thinkers. Hopefully my
terminology is not too far off ;)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,527
Members
45,000
Latest member
MurrayKeync

Latest Threads

Top