From: David Mark on
On Jul 22, 10:16 am, John G Harris <j...(a)nospam.demon.co.uk> wrote:
> On Thu, 22 Jul 2010 at 00:24:04, in comp.lang.javascript, David Mark
> wrote:
>
>   <snip>
>
> >ISTM that the term instances is associated with classes, of which
> >there are none in JS.
>
> 'Instance' is associated with anything that is one of many.

Yes, in general, but it has technical connotations in this context.
But you tell me as I am not an OO expert (and IIRC that is your
specialty).

> You have
> said, I seem to remember, that there are no singleton objects in JS,

So have a lot of people. :) If there are no classes, why would there
be any reason to refer to an object as a "singleton". Another way to
look at it is that they are all singletons in JS (but that will lead
to confusion for those coming from classical OO languages).

> so
> every object must be one of many somethings.

But there are no classes, so technically speaking, there's no need to
introduce the term singleton to describe them as it would imply that
there are objects that are not "singletons". See what I mean?

>
>   <snip>
>
> >I would have called it an Array object.
>
> You are using 'Array' as an adjective here.

Yes. Common practice when discussing types of built-in objects (e.g.
Object object, Number object, etc.)

> This is just a short way of
> saying that it's an object that was created by the constructor named
> Array.

Yes.

>
> Either way, the object is a member of the class of all possible such
> objects.

But you are playing loose with those terms. Technically speaking,
there are no classes in JS.

>
> >Doesn't that make more
> >sense?  Like all JS objects, it is constructed, not instantiated.
>
> I don't believe there is any substantial difference between construct
> and instantiate.

There's definitely a difference and, however minute, using them
interchangeably will only confuse people who understand classical, but
not prototype inheritance.

>
> Occasionally you might want to distinguish between construction, which
> does not include allocating space for the object, and instantiation
> which often does, as in a factory method.

I assume you referring to factory methods on the classical side. But
that would be an obscure bit compared to other differences in the
mechanics of creating objects in prototypal and classical inheritance
schemes.
From: David Mark on
On Jul 22, 1:34 pm, Richard Cornford <Rich...(a)litotes.demon.co.uk>
wrote:
> On Jul 22, 2:48 pm, Josh Russo wrote:
>
>
>
> > On Jul 22, 9:50 am, David Mark wrote:
> >> On Jul 22, 5:08 am, Josh Russo wrote:
> <snip>
> >>> What matter is the scope of the event listener function
> >>> when it's declared.
>
> >> In the case we have been discussing, the listener attached
> >> by jQuery is not declared at all.  It's created with a
> >> function expression inside of a jQuery method.  What do
> >> you figure its scope to be? That's right, you will have to
> >> slog through jQuery's code again to determine whether it is
> >> minding its business with regard to avoiding circular
> >> references.  What your code does is actually immaterial.
> >> Confusing and time-consuming isn't it?
>
> > Ok now you lost me. The lines in question are these:
>
> >       var clickHandler = function(event){ //do something };
> >       this.myfield.bind('click', clickHandler);
>
> > This is not within a jQuery method. jQuery merely stores the
> > reference that I pass to it. The clickHandler function right
> > there outside of the jQuery object, or am I missing something?
>
> <snip>
>
> Not looking does tend to be quite a good way of missing things. Take a
> look at JQuery source code and you find that the - bind - method (more
> or less indirectly) calls a - jQuery.event.add - method. This is its
> source code form the current (1.4.2) version (or at least pertinent
> highlights from the code) (and re-wrapped a little to avoid it being
> broken by Usenet posting):-
>
> | jQuery.event = {
> |
> |   // Bind an event to an element
> |   // Original by Dean Edwards
> |   add: function( elem, types, handler, data ) {
> ...
> |     var events = elemData.events = elemData.events || {},
> |       eventHandle = elemData.handle, eventHandle;
>         ^^^^^^^^^^^                    ^^^^^^^^^^^
> I don't like the form of variable declaration statement that uses a
> single - var - but spreads numerous declarations across multiple
> lines, terminating each in a comma (rather than using multiple
> variable declarations, terminating each line with a semicolon). I
> frequently find myself miss-reading them, and so think of them as not
> being particularly clear in source code terms. Above there is evidence
> of this lack of clarity in the fact that - eventHandle - has been
> declared twice in the same variable declaration statement. There is no
> good reason for doing that (ever) and the intention cannot have been
> to write the equivalent of - eventHandle = (elemData.handle,
> eventHandle) - (as that would be obviously wrong given the next line
> of code), so presumably this 'oddity' has resulted (and survived
> (presumably many observers)) from a failure to comprehend the source
> code as presented.
>
> |     if ( !eventHandle ) {
> |       elemData.handle = eventHandle = function() {
> |         // Handle the second event of a trigger and when
> |         // an event is called after a page has unloaded
> |         return typeof jQuery !== "undefined" &&
> |                              !jQuery.event.triggered ?
> |           jQuery.event.handle.apply( eventHandle.elem, arguments ):
> |           undefined;
> |       };
> |     }
> |
> |     // Add elem as a property of the handle function
> |     // This is to prevent a memory leak with non-native
> |     // events in IE.
> |     eventHandle.elem = elem;
>       ^^^^^^^^^^^^^^^^^^^^^^^
> Here the function either retrieved or created above and assigned to
> the variable - eventHandle - has a property added to it with the name
> 'elem' and a reference to a object that is likely to be a DOM Element
> assigned to it.
>
> JQuery comments never seem to explain the more unexpected aspects of
> what JQuery code does. IE has memory leak problems (or at lest older
> versions of it do), but what does "non-native events" mean, and how is
> this going to prevent the memory leaks?
>
> Possibly the idea is that if the variable - elem - where referenced in
> the - jQuery.event.handle.apply( ... - line above, and not nulled at
> the end of this method, then there would be an obvious circular chain
> of reference, which there would be. But what follows rather negates
> any effort taken to avoid that circle.
>
> |
> |     // Handle multiple events separated by a space
> |     // jQuery(...).bind("mouseover mouseout", fn);
> |     types = types.split(" ");
> |
> |     var type, i = 0, namespaces;
> |
> |     while ( (type = types[ i++ ]) ) {
> ...
> |
> |       // Init the event handler queue
> |       if ( !handlers ) {
> |         handlers = events[ type ] = [];
> |
> |         // Check for a special event handler
> |         // Only use addEventListener/attachEvent if the special
> |         // events handler returns false
> |         if ( !special.setup ||
> |               special.setup.call(
> |                   elem, data, namespaces, eventHandle
> |               ) === false
> |         ) {
> |           // Bind the global event handler to the element
> |           if ( elem.addEventListener ) {
> |             elem.addEventListener( type, eventHandle, false );
> |
> |           } else if ( elem.attachEvent ) {
> |             elem.attachEvent( "on" + type, eventHandle );
>               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> And there the circle is closed. (on IE, which is where it will matter)
> The (likely DOM Element) referred to by - elem - is given a reference
> to the - eventHandle - function through the - attachEvent - mechanism,
> while the - eventHandle - has a reference to the - elem - object
> through the 'elem' property that was assigned above. That is a
> circular chain of reference, established (albeit only once, but once
> is enough) for each event type, for each unique - elem - passed into
> the - add - method.
>
> |           }
> |         }
> |       }
> ...
> |   elem = null;
> |   },
> ...
>
> Outside of JQuery you can do whatever you like to avoid the memory
> leak-inducing circular chains of references, but JQuery creates them
> for you when you use its - bind - method. Now the question is whether
> JQuery cleans these circular chains of reference up on its own, or
> whether you are going to have to take some remedial action to remove
> bound methods; time to "slog through jQuery's code again". And if it
> turns out that you have to take action yourself then maybe you don't
> have to avoid creating circular chins of reference as you would have
> the opportunity to break any you did create at the same time as you
> set about breaking JQuery's.
>

IIRC, they use an unload listener to offset their own previous
mistakes as used to be preached by Douglas Crockford (and hopefully
he's since renounced the strategy). Of course, they'd have been much
better off avoiding (or fixing) the mistakes. :)

The idea that such listeners are unneeded (and can be very
destructive) has only just started to reach the general public (years
late as usual). As usual, jQuery's authors are at the rear of the
pack. They'll get it eventually (maybe even after reading this
thread).
From: Thomas 'PointedEars' Lahn on
David Mark wrote:

> Thomas 'PointedEars' Lahn wrote:
>> David Mark wrote:
>> > Josh Russo wrote:
>> >> David Mark wrote:
>> >> > The objects that jQuery's "$" function return are somewhat
>> >> > array-like but have nothing to do with arrays. They are simply
>> >> > Object objects (as opposed to Array objects).
>>
>> >> You are correct. I took a look again and they are creating objects
>> >> with array like properties. What I thought they were doing was adding
>> >> custom functions/methods to an array instance.
>> ^^^^^
>>
>> > There are no instances in JS. :)
>>
>> Wrong. You want to read the ECMAScript Language Specification, any
>> Edition.
>
> ISTM that the term instances is associated with classes,

No doubt about that. But not exclusively to class-based OOP.

> of which there are none in JS.

That would depend on what one understands "classes" and "JS" to be,
especially the latter.

> Of course the language used in specifications can often be confusing when
> dropped into a general discussion.

But not in this case. I am not saying that the OP was aware that they were
referring to the wrong thing by the right name (it is rather likely that
they were not, given common misconceptions about these languages); I am
saying that your statement in its absoluteness is simply wrong.

> [snip red herring]

>> The term that has been used here is only incorrect in that it should have
>> been a capital `A' at the beginning.
>
> I would have called it an Array object.

I would have a few years ago; not anymore.

> Doesn't that make more sense?

No. If we adopt the custom that for simplicity the name of the property
that refers to an object is used as the name of that object (see "window
object" aso.), then "Array object" would specify the Array constructor, a
Function instance, instead.

> Like all JS objects, it is constructed, not instantiated.

We've been over this. The term instance as used in the Specification (and I
am not talking about `instanceof') helps to differentiate between the object
created with a constructor and the constructor object itself, to begin with.
Like many other terms in the Specification. It does not make sense to
invent different terminology when the existing one suffices.


HTH

PointedEars
--
Anyone who slaps a 'this page is best viewed with Browser X' label on
a Web page appears to be yearning for the bad old days, before the Web,
when you had very little chance of reading a document written on another
computer, another word processor, or another network. -- Tim Berners-Lee
From: David Mark on
On Jul 22, 6:13 pm, Thomas 'PointedEars' Lahn <PointedE...(a)web.de>
wrote:
> David Mark wrote:
> > Thomas 'PointedEars' Lahn wrote:
> >> David Mark wrote:
> >> > Josh Russo wrote:
> >> >> David Mark wrote:
> >> >> > The objects that jQuery's "$" function return are somewhat
> >> >> > array-like but have nothing to do with arrays.  They are simply
> >> >> > Object objects (as opposed to Array objects).
>
> >> >> You are correct. I took a look again and they are creating objects
> >> >> with array like properties. What I thought they were doing was adding
> >> >> custom functions/methods to an array instance.
> >>                                   ^^^^^
>
> >> > There are no instances in JS.  :)
>
> >> Wrong.  You want to read the ECMAScript Language Specification, any
> >> Edition.
>
> > ISTM that the term instances is associated with classes,
>
> No doubt about that.  But not exclusively to class-based OOP.

Well, as there are no classes in JS...

>
> > of which there are none in JS.
>
> That would depend on what one understands "classes" and "JS" to be,
> especially the latter.

As you likely know, I am referring to ECMAScript implementations (e.g.
JScript, JavaScript, etc.)

>
> > Of course the language used in specifications can often be confusing when
> > dropped into a general discussion.
>
> But not in this case.  I am not saying that the OP was aware that they were
> referring to the wrong thing by the right name (it is rather likely that
> they were not, given common misconceptions about these languages); I am
> saying that your statement in its absoluteness is simply wrong.

I suppose it depends on perspective.

>
> > [snip red herring]
> >> The term that has been used here is only incorrect in that it should have
> >> been a capital `A' at the beginning.
>
> > I would have called it an Array object.
>
> I would have a few years ago; not anymore.
>
> > Doesn't that make more sense?
>
> No.  If we adopt the custom that for simplicity the name of the property
> that refers to an object is used as the name of that object (see "window
> object" aso.), then "Array object" would specify the Array constructor, a
> Function instance, instead.

Interesting twist, but when I say "window object", I am referring to
the object. The fact that it is referenced by a property of the
Global Object doesn't really enter into it.

>
> > Like all JS objects, it is constructed, not instantiated.
>
> We've been over this.  The term instance as used in the Specification (and I
> am not talking about `instanceof') helps to differentiate between the object
> created with a constructor and the constructor object itself, to begin with.  

Yes, I suppose it is more concise than saying the "constructed
object", but still the term "instance" is part of what leads to
confusion among those who are used to class-based languages.


> Like many other terms in the Specification.  It does not make sense to
> invent different terminology when the existing one suffices.

Who's inventing?
From: Richard Cornford on
David Mark wrote:
> On Jul 22, 1:34 pm, Richard Cornford wrote:
>>> On Jul 22, 9:50 am, David Mark wrote:
<snip>
>>>> That's right, you will have to slog through jQuery's code
>>>> again to determine whether it is minding its business with
>>>> regard to avoiding circular references. What your code does
>>>> is actually immaterial. Confusing and time-consuming isn't it?
<snip>
>> Outside of JQuery you can do whatever you like to avoid the
>> memory leak-inducing circular chains of references, but JQuery
>> creates them for you when you use its - bind - method. Now the
>> question is whether JQuery cleans these circular chains of
>> reference up on its own, or whether you are going to have to
>> take some remedial action to remove bound methods; time to "slog
>> through jQuery's code again". And if it turns out that you have
>> to take action yourself then maybe you don't have to avoid
>> creating circular chins of reference as you would have
>> the opportunity to break any you did create at the same
>> time as you set about breaking JQuery's.
>>
>
> IIRC, they use an unload listener to offset their own previous
> mistakes as used to be preached by Douglas Crockford (and
> hopefully he's since renounced the strategy). Of course, they'd
> have been much better off avoiding (or fixing) the mistakes. :)

If you want someone to experience the 'joys' of searching through the
sauce code of a highly interdependent javascript library in order to
find a definitive answer to a specific question then it does not seem
like a good idea to tell then the answer before hand.

Unload handlers address some of the issues but they leave the question
of what happens in the meanwhile. If an unbroken circular chain of
references is going to prevent garbage collection until the browser is
shut down, effected DOM elements that are removed/freed/replaced are not
going to be garbage collected themselves in the meanwhile. This would
become an issue in the 'single page' style of web application, where you
are expected to use the application for some time before unloading it.
Quite a few DOM Elements, some with event handlers, are likely to be
cycled through the DOM, and normally once they are finished with the
desire would be to have the objects garbage collected (especially as IE
6's performance drops off as its memory consumption increases). An
unload handler based approach is not sufficiently proactive as to
achieve that.

> The idea that such listeners are unneeded (and can be very
> destructive) has only just started to reach the general public
> (years late as usual). As usual, jQuery's authors are at the
> rear of the pack. They'll get it eventually (maybe even after
> reading this thread).

The memory leak issues are reducing with the passage of time. Even IE 6
appears to have had updates that reduce the scope of the problem. We may
not be that far away from the end of whole circular reference issue, and
so be able to stop worrying about this entirely.

Richard.