Function declaration inside other function

Discussion in 'Javascript' started by Larax, Dec 7, 2006.

  1. Larax

    Larax Guest

    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
    Larax, Dec 7, 2006
    #1
    1. Advertising

  2. Larax

    Matt Kruse Guest

    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
    Matt Kruse, Dec 7, 2006
    #2
    1. Advertising

  3. 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.
    Richard Cornford, Dec 7, 2006
    #3
  4. Larax

    Larax Guest

    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
    Larax, Dec 7, 2006
    #4
  5. Larax

    VK Guest

    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>
    VK, Dec 7, 2006
    #5
  6. 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.
    Richard Cornford, Dec 7, 2006
    #6
  7. Larax

    RobG Guest

    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/example_scripts/finalizer.html >
    RobG, Dec 8, 2006
    #7
  8. Larax

    Matt Kruse Guest

    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
    Matt Kruse, Dec 8, 2006
    #8
  9. Larax

    VK Guest

    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...
    VK, Dec 8, 2006
    #9
  10. 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.
    Richard Cornford, Dec 8, 2006
    #10
  11. Larax

    VK Guest

    Richard Cornford wrote:
    > 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? :)

    <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.


    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?

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

    > > 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.


    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.
    VK, Dec 8, 2006
    #11
  12. In comp.lang.javascript message
    <>, Fri, 8 Dec 2006
    03:09:03, VK <> wrote:
    >
    >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.

    --
    (c) John Stockton, Surrey, UK. ?@merlyn.demon.co.uk Turnpike v6.05 MIME.
    Web <URL:http://www.merlyn.demon.co.uk/> - FAQqish topics, acronyms & links;
    Astro stuff via astron-1.htm, gravity0.htm ; quotings.htm, pascal.htm, etc.
    No Encoding. Quotes before replies. Snip well. Write clearly. Don't Mail News.
    Dr J R Stockton, Dec 8, 2006
    #12
  13. VK wrote:
    > Richard Cornford wrote:
    >> VK wrote:
    >>> 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.

    >
    > fricking cold (43F), clouds, someone's called your
    > yesterday article "deranged ramblings". What more
    > anyone would want for a really good morning? :)
    > <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.

    >
    > 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.

    <snip>
    > 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.


    > ///////////////////////
    >
    >>> 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.

    >
    > 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.
    Richard Cornford, Dec 9, 2006
    #13
  14. Larax

    VK Guest

    Richard Cornford wrote:

    <snip>

    > > 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?


    Oops... I meant new Function, sorry. see
    <http://groups.google.com/group/comp.lang.javascript/msg/fc4bd916619ef0c9>

    <snip>
    VK, Dec 9, 2006
    #14
  15. Larax

    VK Guest

    Richard Cornford wrote:
    > 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.
    VK, Dec 9, 2006
    #15
  16. VK wrote:
    > Richard Cornford wrote:
    >> VK wrote:

    <snip>
    >>> 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;


    >
    > 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.

    > see
    >

    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.
    Richard Cornford, Dec 10, 2006
    #16
  17. VK wrote:
    > Richard Cornford wrote:
    >> 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).


    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.
    Richard Cornford, Dec 10, 2006
    #17
  18. Larax

    VK Guest

    Richard Cornford wrote:
    > 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>
    </html>

    > 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.
    VK, Dec 10, 2006
    #18
  19. VK wrote:
    > Richard Cornford wrote:
    >> 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.

    >>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.


    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?

    >> 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?


    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.

    >> 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.


    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="">
    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.
    Richard Cornford, Dec 10, 2006
    #19
  20. Larax

    Matt Kruse Guest

    Richard Cornford wrote:
    > 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 ;)

    --
    Matt Kruse
    http://www.JavascriptToolbox.com
    http://www.AjaxToolbox.com
    Matt Kruse, Dec 10, 2006
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ovidesvideo
    Replies:
    4
    Views:
    502
    Andrey Tarasevich
    Dec 10, 2004
  2. Replies:
    4
    Views:
    1,075
    Richard Tobin
    Dec 12, 2006
  3. Bolin
    Replies:
    4
    Views:
    408
  4. Luca Forlizzi
    Replies:
    4
    Views:
    460
    Luca Forlizzi
    Nov 14, 2010
  5. Mehmet Yavuz S. Soyturk

    variable declaration inside eval inside with

    Mehmet Yavuz S. Soyturk, Apr 11, 2007, in forum: Javascript
    Replies:
    3
    Views:
    125
    Mehmet Yavuz S. Soyturk
    Apr 12, 2007
Loading...

Share This Page