How to ensure memory leak protection?

J

Josh Russo

I'm a little confused about how best to handle user objects that
manage multiple DOM objects.

I was reading https://developer.mozilla.org/en/a_re-introduction_to_javascript
and it seems like my preferred pattern seems like it's exactly what
I'm not suppose to do.

function Widget(){
this.myfield = $('#id_myfield');
var clickHandler = function(event){ //do something };
this.myfield.bind('click', clickHandler);
}

myWdgt = new Widget();

It seems like this is the proper way to handle the issue is this:

function Widget(){
var clickHandler = function(event){ //do something };
(function(){
var myfield = $('#id_myfield');
myfield.bind('click', clickHandler);
})();
}

The only problem with this is that I don't get to cache the query of
MyField. Do I really need to re-query MyField in every method that
needs to use it? It just seems like so much more processing. Though if
that's the only way to avoid the memory leaks then so be it.

The other possibility I see is to capture the window.unload event to
manually destroy my objects. If I do this, is it enough to just
destroy my Widget instances or do I need to destroy the DOM references
individually within each Widget instance?

Thanks so much for your help.

Josh
 
D

David Mark

I'm a little confused about how best to handle user objects that
manage multiple DOM objects.

Object objects that wrap multiple host objects? Not sure why multiple
matters though.
I was readinghttps://developer.mozilla.org/en/a_re-introduction_to_javascript
and it seems like my preferred pattern seems like it's exactly what
I'm not suppose to do.

function Widget(){
      this.myfield = $('#id_myfield');

Well, that's a big red flag as it indicates one of those ill-conceived
libraries (e.g. jQuery). Why would you use that $ function in lieu of
gEBI?
      var clickHandler = function(event){ //do something };
      this.myfield.bind('click', clickHandler);

What about it? There's really no telling what it does exactly without
reading the source of the library. And isn't that what you want to
avoid in the first place. Why not use a simple wrapper for
addEventListener/attachEvent?
}

myWdgt = new Widget();

It seems like this is the proper way to handle the issue is this:

function Widget(){
      var clickHandler = function(event){ //do something };
      (function(){
            var myfield = $('#id_myfield');
            myfield.bind('click', clickHandler);
      })();

}

What makes you think that is more proper (or less prone to leaks) than
the above? I assure you it is not. In fact, it's completely bizarre.
The only problem with this is that I don't get to cache the query of
MyField.

You weren't caching anything in the first place.
Do I really need to re-query MyField in every method that
needs to use it?

No, but that question bears little resemblance to the above cases.
There are no method calls in either of them.
It just seems like so much more processing. Though if
that's the only way to avoid the memory leaks then so be it.

You are clearly confused about a number of things. Here is some basic
information on the IE memory leak issue:-

http://www.jibbering.com/faq/notes/closures/#clMem

....that is not published by a member of a cargo cult.
The other possibility I see is to capture the window.unload event to
manually destroy my objects.

Try as you might, you'll never destroy an object in JS. You can
remove all references to an object and eventually the built-in GC will
release the associated resources. That being said, there is no need
to do anything like that in the unload event. That practice became
popular because library developers were trying to solve a problem (of
their own creation) that they didn't understand. Now you are
following in their footsteps.
If I do this, is it enough to just
destroy my Widget instances or do I need to destroy the DOM references
individually within each Widget instance?

You don't need to do anything like that. And the DOM references you
refer to are not "within" the widgets. They are preserved in
closures, which may or may not create circular references. If they do
create such chains then the only way to prevent the leaks in IE is to
remove one or more of the links (e.g. detach the listener from the
element).

Your best bet is to understand the root cause of the problem and stop
using dubious libraries that cloud the issues. Then you can avoid the
problem altogether and never worry about leaks or unload listeners
again.
 
J

Josh Russo

Object objects that wrap multiple host objects?  Not sure why multiple
matters though.

It doesn't matter. One is enough.
Well, that's a big red flag as it indicates one of those ill-conceived
libraries (e.g. jQuery).  Why would you use that $ function in lieu of
gEBI?

Ok, there's no need to critique my choice libraries. Thanks. The same
would apply if I had said:

this.myfield = document.getElementById('id_myfield');

What about it?  There's really no telling what it does exactly without
reading the source of the library.  And isn't that what you want to
avoid in the first place.  Why not use a simple wrapper for
addEventListener/attachEvent?

Because of closures the clickHandler scope keeps the this.myfile in
context. Of course I just realized that the 'this' keyword would be
overridden in the actual call of the click event. When the event is
called 'this' will be the myfield instance. The following is a better
example:

function Widget(){
var myfield = $('#id_myfield');
var clickHandler = function(event){ //do something };
myfield.bind('click', clickHandler);
}

Here the myfield DOM object has a circular reference to itself via the
myfield variable.
What makes you think that is more proper (or less prone to leaks) than
the above?  I assure you it is not.  In fact, it's completely bizarre..

It's more correct because the myfield var goes out of scope after use
because the clickHandler can't see it.

You weren't caching anything in the first place.

I was caching the reference to the DOM object id_myfield in
this.myfield, of course var myfield would accomplish the same goal
without making it a public property. My goal is to not have to use
getElementById or any other querying mechanism every time I want to
use a field.

No, but that question bears little resemblance to the above cases.
There are no method calls in either of them.

Ok, you are correct. I didn't add them explicitly, I figured people
could envision what I was referring to. Here's an example:
function Widget(){
this.myfield = $('#id_myfield');
var clickHandler = function(event){ //do something };
this.myfield.bind('click', clickHandler);

this.setField = function(txt){
this.myfield.val(txt); // Yes it's jQuery syntax
}
}

You are clearly confused about a number of things.  Here is some basic
information on the IE memory leak issue:-

http://www.jibbering.com/faq/notes/closures/#clMem

...that is not published by a member of a cargo cult.

The document you directed me to explains exactly the situation I'm
referring to. This is directly from that page:

Closures are extremely good at forming circular references. If a
function object that forms a closure is assigned as, for example, and
event handler on a DOM Node, and a reference to that Node is assigned
to one of the Activation/Variable objects in its scope chain then a
circular reference exists. DOM_Node.onevent -> function_object.
[[scope]] -> scope_chain -> Activation_object.nodeRef -> DOM_Node. It
is very easy to do, and a bit of browsing around a site that forms
such a reference in a piece of code common to each page can consume
most of the systems memory (possibly all).

Try as you might, you'll never destroy an object in JS.  You can
remove all references to an object and eventually the built-in GC will
release the associated resources.  That being said, there is no need
to do anything like that in the unload event.  That practice became
popular because library developers were trying to solve a problem (of
their own creation) that they didn't understand.  Now you are
following in their footsteps.

Ok, so what you just did was answer the next part of my question. I
may need to manually dereference the individual references, using the
delete command.
You don't need to do anything like that.  And the DOM references you
refer to are not "within" the widgets.  They are preserved in
closures, which may or may not create circular references.  If they do
create such chains then the only way to prevent the leaks in IE is to
remove one or more of the links (e.g. detach the listener from the
element).

They are in a circular reference as described by the page you
referenced.
 
D

David Mark

It doesn't matter. One is enough.



Ok, there's no need to critique my choice libraries.

You would do well to listen. It's not just the odd $ function that I
dislike about it. The fact is that the code throughout is of very
poor quality.
Thanks. The same
would apply if I had said:

this.myfield = document.getElementById('id_myfield');

But that's totally different as gEBI returns a host object reference.
The jQuery thing returns an Object object. See how using a library at
a point where you don't understand the basics can be confusing? Along
the same lines, you are likely not ready to judge the quality (or lack
thereof) of the libraries either.
Because of closures the clickHandler scope keeps the this.myfile in
context.

You are confused. The - this - keyword is not part of the scope
chain. There is no reference to a host object in the scope of your
listener function and furthermore, the library is unlikely to attach
that function as the listener (more likely it wraps it, but again
there's no telling without delving into jQuery). Until you understand
these concepts, libraries will just make such potential issues harder
to spot.
Of course I just realized that the 'this' keyword would be
overridden in the actual call of the click event.

Very likely it will reference the element, but that doesn't matter.
When the event is
called 'this' will be the myfield instance.

There are no instances in JS and "myfield" is the name of a property
of your constructed object, which references another Object object
(not a host object). That's if you are using jQuery. If it is
Prototype or MooTools, it will reference a host object, but it still
won't matter as the - this - keyword is not part of the scope chain.
The following is a better
example:

function Widget(){
      var myfield = $('#id_myfield');
      var clickHandler = function(event){ //do something };
      myfield.bind('click', clickHandler);

}

Here the myfield DOM object has a circular reference to itself via the
myfield variable.

If the myfield variable references an element (host object) rather
than some sort of wrapper (Object object) then this could possibly be
a leaky pattern. But I find it extremely unlikely that the bind
method attaches your clickHandler function as the listener (more
likely it wraps it in another function). Again, it's hard to say
without looking into the library code (which is likely what you are
trying to avoid by using a library). By using such a library, you
have created problems for yourself, as well as for anyone who would
try to debug the code (e.g. me).
It's more correct because the myfield var goes out of scope after use
because the clickHandler can't see it.

That indicates some understanding of the problem; but again, it is
unclear whether there was a problem in the first place.

And why not do this:-

function Widget() {
var el = document.getElementById('id_myfield');

el.onclick = function() {
// Do something
};
el = null;
}

It should be clear that without the last line, there would be a
circular reference involving a host object (and therefore it would
leak in some versions of IE). Also, the - this - keyword will
reference the element, so you don't need to preserve it.

If your listener will need a reference to the constructed object,
add:-

var that = this;

If you don't need a reference to your constructed object, you could do
this:-

function clickListener() {
// Do something
}

function Widget() {
var el = document.getElementById('id_myfield');

el.onclick = clickListener;
}

Hard to say from your examples, but assuming you do need such a
reference:-

function createClickListener(that) {
return function() {
// Do something
};
}

function Widget() {
var el = document.getElementById('id_myfield');

el.onclick = createClickListener(this);
}
I was caching the reference to the DOM object id_myfield in
this.myfield, of course var myfield would accomplish the same goal
without making it a public property.

I didn't see how you considered that caching as every call to the
constructor would repeat that operation. But I see what you are
getting at now.
My goal is to not have to use
getElementById or any other querying mechanism every time I want to
use a field.

You haven't posted any examples that use the element (or wrapped
element) reference, so it is hard to follow what you are trying to do.
Ok, you are correct. I didn't add them explicitly, I figured people
could envision what I was referring to.

There are few mind-readers here.

Here's an example:
function Widget(){
      this.myfield = $('#id_myfield');
      var clickHandler = function(event){ //do something };
      this.myfield.bind('click', clickHandler);

      this.setField = function(txt){
         this.myfield.val(txt); // Yes it's jQuery syntax
      }

}

And there are very few who care to dig through jQuery to determine
whether your assumptions about its methods are correct. But
regardless, the above has no circular reference (with or without
jQuery). The - this - keyword is not part of the scope chain and
jQuery's "$" method does not return host objects anyway. The only
thing that could create leaks here is jQuery and therefore the only
way to know for sure whether leaks will occur is to read jQuery's
code, which negates the benefit of using the library.

Consider this more readable alternative, which does not require any
odd patteners or an additional 70K of junk code:-

function createClickListener(that) {
return function() {
// Do something with this and that
};
}

function Widget(){
      el = document.getElementById('id_myfield');
      el.onclick = createClickListener(this);

      this.setField = function(txt) {
         el.value = txt;
      };
}

In your listener - this - will refer to the element and - that - will
refer to the widget object.

That's much faster, more readable and obviously much less code to pore
over and maintain.
The document you directed me to explains exactly the situation I'm
referring to.

But apparently you did not understand it.
This is directly from that page:

Closures are extremely good at forming circular references. If a
function object that forms a closure is assigned as, for example, and
event handler on a DOM Node, and a reference to that Node is assigned
to one of the Activation/Variable objects in its scope chain then a
circular reference exists. DOM_Node.onevent -> function_object.
[[scope]] -> scope_chain -> Activation_object.nodeRef -> DOM_Node. It
is very easy to do, and a bit of browsing around a site that forms
such a reference in a piece of code common to each page can consume
most of the systems memory (possibly all).

Yes, I've read it. But pasting snippets here will not help you
understand why - this - is not part of the scope chain.
Ok, so what you just did was answer the next part of my question. I
may need to manually dereference the individual references, using the
delete command.

Not in the case of your examples as - this - is not part of the scope
chain.
They are in a circular reference as described by the page you
referenced.

Which you have failed to understand completely.
 
J

Josh Russo

Ok, lets start over.

First off I know exactly what jQuery is doing behind the scenes. The
object that it creates extends the array class. Each element of said
array is a DOM object. All additional jQuery helper methods are added
to the extended array class. Are you saying that because the DOM
elements are elements of a fancy array that it's no longer a circular
reference? That doesn't sound right. Maybe if these array elements
were not publicly accessible, but they are, so it sees that there
would still be a circular reference using a jQuery object as opposed
to a direct DOM element.

I guess the crux of my difficulty is that I want to avoid multiple
calls to methods like gEBI or $(). I think you hit my solution with
this bit:

function clickListener() {
// Do something
}

function Widget() {
var el = document.getElementById('id_myfield');
el.onclick = clickListener;
}

I just got too wrapped up in having everything encapsulated in the
class/function.

Thanks for talking me through that.
 
D

David Mark

Ok, lets start over.

First off I know exactly what jQuery is doing behind the scenes.

That would tend to contradict your previous questions regarding your
examples. And why waste time being defensive?
The
object that it creates extends the array class.

There is no such thing as an "array class" and jQuery doesn't extend
anything native. Clearly you are very confused. I know that sounds
harsh, but it is what you need to hear at this point. You might feel
compelled to blame me for your confusion (and possible frustration at
this point), but it is surely schlock like Prototype, Dojo, MooTools,
ExtJS, etc. that has led you astray. jQuery's code is less schlocky
in this regard, but the community is such a cargo cult that I'm sure
they repeat such misconceptions about "classes", "singletons", scope,
etc. Granted, you seem to have scope about half right (which is above
the industry average).

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).
Each element of said
array is a DOM object.

I'm imagine it does maintain an array internally. And I believe it
mirrors the DOM references as properties of the object. That is
certainly a bad idea. In the case of one of your examples, you
*might* have had this chain:-

[jQuery object]->[DOM node]->[listener function]->[Activation Object]-
[jQuery object]

But certainly that would not be the case where you "cached" the
reference to the element as a property of your constructed object as
the fourth link in that chain would not exist. Furthermore, in your
other examples, assuming jQuery wraps listeners (a good bet as it
allows you to set the - this - object), the same link would be
broken. So it seems likely that you are chasing phantoms.
All additional jQuery helper methods are added
to the extended array class.

See above about that. Realize that JS uses prototypal (not classical)
inheritance. The "helper methods" you refer to are on the jQuery
object's prototype (jquery.fn IIRC).
Are you saying that because the DOM
elements are elements of a fancy array that it's no longer a circular
reference?

Certainly not as there is no such thing as a "fancy array".
That doesn't sound right. Maybe if these array elements
were not publicly accessible, but they are, so it sees that there
would still be a circular reference using a jQuery object as opposed
to a direct DOM element.

Except for the reasons I already pointed out (e.g. the - this -
keyword is not part of the scope chain).
I guess the crux of my difficulty is that I want to avoid multiple
calls to methods like gEBI or $(). I think you hit my solution with
this bit:

function clickListener() {
  // Do something

}

function Widget() {
  var el = document.getElementById('id_myfield');
  el.onclick = clickListener;

}

I just got too wrapped up in having everything encapsulated in the
class/function.

Thanks for talking me through that.

NP at all. Best of luck!
 
J

Josh Russo

That would tend to contradict your previous questions regarding your
examples.  And why waste time being defensive?

My question wasn't about how jQuery works. I was already convinced
that the object created by jQuery was creating the same scenario you
have if you had a direct DOM reference instead. In other words you can
replace any $() calls with gEBI and have the same scenario. My
question, if you reference my original post, was about user object
creation patterns.

People tend to get defensive when you criticize instead of just asking
question about their methods. You may have asked questions, but in a
very critical manner.

There is no such thing as an "array class" and jQuery doesn't extend
anything native.  Clearly you are very confused.  I know that sounds
harsh, but it is what you need to hear at this point.  You might feel
compelled to blame me for your confusion (and possible frustration at
this point), but it is surely schlock like Prototype, Dojo, MooTools,
ExtJS, etc. that has led you astray.  jQuery's code is less schlocky
in this regard, but the community is such a cargo cult that I'm sure
they repeat such misconceptions about "classes", "singletons", scope,
etc.  Granted, you seem to have scope about half right (which is above
the industry average).

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.

I have only a cursory understanding of prototyping. I thought it was
just in memory classes. I will make sure I understand it and use it's
terminology more.

By the way, what in the world do you mean by a cargo cult?

Each element of said
array is a DOM object.

I'm imagine it does maintain an array internally.  And I believe it
mirrors the DOM references as properties of the object.  That is
certainly a bad idea.  In the case of one of your examples, you
*might* have had this chain:-

[jQuery object]->[DOM node]->[listener function]->[Activation Object]-
[jQuery object]

But certainly that would not be the case where you "cached" the
reference to the element as a property of your constructed object as
the fourth link in that chain would not exist.  Furthermore, in your
other examples, assuming jQuery wraps listeners (a good bet as it
allows you to set the - this - object), the same link would be
broken.  So it seems likely that you are chasing phantoms.

Yes I realize now that I will be safe if I setup the DOM reference as
a public property of the my Widget object using the 'this' keyword.
There is a problem though if I want to make the DOM reference private
by using 'var' instead.
 
E

Erwin Moller

Josh Russo schreef:
By the way, what in the world do you mean by a cargo cult?

http://en.wikipedia.org/wiki/Cargo_cult_programming

which is based on Richard Feynman original:

http://en.wikipedia.org/wiki/Cargo_cult_science

The other issues I rather leave to David to answer. ;-)

Regards,
Erwin Moller



--
"There are two ways of constructing a software design: One way is to
make it so simple that there are obviously no deficiencies, and the
other way is to make it so complicated that there are no obvious
deficiencies. The first method is far more difficult."
-- C.A.R. Hoare
 
D

David Mark

My question wasn't about how jQuery works.

But you posted a code snippet without even specifying that jQuery was
in use.
I was already convinced
that the object created by jQuery was creating the same scenario you
have if you had a direct DOM reference instead.

But you apparently didn't realize how jQuery attaches listeners.
In other words you can
replace any $() calls with gEBI and have the same scenario. My
question, if you reference my original post, was about user object
creation patterns.

And there was a huge hole in the example you posted, which inhibited
prospective respondents from deducing what your real problem was (or
if there was a problem at all). If your question was strictly about
JS patterns, you should have posted a "pure" example (i.e. one that
did not call functions in a black hole).
People tend to get defensive when you criticize instead of just asking
question about their methods.

I didn't criticize you at all.
You may have asked questions, but in a
very critical manner.

Critical thinking requires critical questions. Though perhaps you
have another take on that term.

I was only asking such questions to get to the bottom of your problem
and to save both of us some time in the process. You should also
remember this is not a help desk.
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. :)
I have only a cursory understanding of prototyping.

Clearly and that is a major obstacle for JS proficiency. Part of my
"criticism" was to alert you to that fact.
I thought it was
just in memory classes.

I don't know what that means.
I will make sure I understand it and use it's
terminology more.

You are welcome. :)
By the way, what in the world do you mean by a cargo cult?

That's been answered in a follow-up. JFTR, jQuery is one of the
biggest (and loudest).
I'm imagine it does maintain an array internally.  And I believe it
mirrors the DOM references as properties of the object.  That is
certainly a bad idea.  In the case of one of your examples, you
*might* have had this chain:-
[jQuery object]->[DOM node]->[listener function]->[Activation Object]-
[jQuery object]
But certainly that would not be the case where you "cached" the
reference to the element as a property of your constructed object as
the fourth link in that chain would not exist.  Furthermore, in your
other examples, assuming jQuery wraps listeners (a good bet as it
allows you to set the - this - object), the same link would be
broken.  So it seems likely that you are chasing phantoms.

Yes I realize now that I will be safe if I setup the DOM reference as
a public property of the my Widget object using the 'this' keyword.

Well, if you knew that before, why did you post examples that assumed
such an arrangement would leak?
There is a problem though if I want to make the DOM reference private
by using 'var' instead.

There could be. As mentioned, it depends on how your library attaches
listeners.
 
T

Thomas 'PointedEars' Lahn

Josh said:
First off I know exactly what jQuery is doing behind the scenes.

You think you do, but you don't. For not even its author(s) do(es). We've
be over this ad nauseam. You would be well-advised to read before you post.


PointedEars
 
T

Thomas 'PointedEars' Lahn

David said:
^^^^^
There are no instances in JS. :)

Wrong. You want to read the ECMAScript Language Specification, any Edition.

The term that has been used here is only incorrect in that it should have
been a capital `A' at the beginning.


PointedEars
 
D

David Mark

                                  ^^^^^


Wrong.  You want to read the ECMAScript Language Specification, any Edition.

ISTM that the term instances is associated with classes, of which
there are none in JS. Of course the language used in specifications
can often be confusing when dropped into a general discussion. For
example, the DOM specifications refer to DOM properties as some sort
of attributes.

And, as has been discussed repeatedly, the instanceof operator has an
unfortunate name. This may have been a case of the language designers
letting the low-level terminology bubble up into the language itself.
In any event, that name has caused confusion.
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. Doesn't that make more
sense? Like all JS objects, it is constructed, not instantiated.
 
J

Josh Russo

Ok, my original post assumed too much. I should have made the
following statements clear:

1) The jQuery object reference offers the same pit falls as a
variable containing a DOM reference because the contained DOM
reference is publicly accessible within the jQuery object

2) Here I was going to say that the bind method works sufficiently
similar to the direct event binding but that doesn't even matter in
this case. What matter is the scope of the event listener function
when it's declared. So #1 is the only thing I really missed in my
original post.

If there are no instances in JS, how do you refer to X and Y below?

var X = [];
var Y = [];

As for learning more about prototyping and how it's different, do you
have a recommendation for a good reference website?
 
D

David Mark

Ok, my original post assumed too much. I should have made the
following statements clear:

   1) The jQuery object reference offers the same pit falls as a
variable containing a DOM reference because the contained DOM
reference is publicly accessible within the jQuery object

Yes, that would have been very helpful for those attempting to
understand the problem or determine whether there actually was a
problem to solve.
   2) Here I was going to say that the bind method works sufficiently
similar to the direct event binding but that doesn't even matter in
this case.

Yes, it certainly does.
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?
So #1 is the only thing I really missed in my
original post.

Do you recall that article by Richard Cornford that I cited and you
quoted a few messages back? You should read it again.
If there are no instances in JS, how do you refer to X and Y below?

var X = [];
var Y = [];

Bad form? :) But seriously, the X and Y variables refer to Array
objects.
As for learning more about prototyping and how it's different, do you
have a recommendation for a good reference website?

I know at least one good article (see above).

And, of course, Crockford has written extensively on the subject as
well.

http://www.crockford.com

Glad you could take something out of this discussion. You'll very
likely become a better programmer for it. Kudos for asking here
rather than in the jQuery forums. There you would have likely gotten
a bunch of "try this" responses with instructions to gaze at the Task
Manager to gauge their effectiveness. It may have been a more
pleasant experience (like visiting a tropical island with endearing
natives), but you would have wasted time and learned nothing (probably
leading to more wasted time in the future).
 
J

Josh Russo

Yes, it certainly does.


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?
So #1 is the only thing I really missed in my
original post.

Do you recall that article by Richard Cornford that I cited and you
quoted a few messages back?  You should read it again.


If there are no instances in JS, how do you refer to X and Y below?
var X = [];
var Y = [];

Bad form?  :)  But seriously, the X and Y variables refer to Array
objects.

Why is this bad form?

I understand that X and Y refer to Array objects but I'm looking from
the variables perspective, I'm talking about how to refer to them from
my perspective. Would they not be Array object instances?

I know at least one good article (see above).

Are you referring to the jibbering.com url?

And, of course, Crockford has written extensively on the subject as
well.

http://www.crockford.com

Glad you could take something out of this discussion.  You'll very
likely become a better programmer for it.  Kudos for asking here
rather than in the jQuery forums.  There you would have likely gotten
a bunch of "try this" responses with instructions to gaze at the Task
Manager to gauge their effectiveness.  It may have been a more
pleasant experience (like visiting a tropical island with endearing
natives), but you would have wasted time and learned nothing (probably
leading to more wasted time in the future).

I always want to know how things really work and in that it helps to
speak the language so everyone is on the same page.
 
A

Asen Bozhilov

Josh said:
I'm a little confused about how best to handle user objects that
manage multiple DOM objects.

I was readinghttps://developer.mozilla.org/en/a_re-introduction_to_javascript
and it seems like my preferred pattern seems like it's exactly what
I'm not suppose to do.

function Widget(){
      this.myfield = $('#id_myfield');
      var clickHandler = function(event){ //do something };
      this.myfield.bind('click', clickHandler);

}

Just rewrite it in a proper way.

var Widget = (function () {
function onClick(evt) {
//...
}

return function (widgetId) {
this.myfield = document.getElementById(widgetId);

util.addListener(this.myfield, 'click', onClick);
};
})();

/**
* Do something with `myfield' member
*/
Widget.prototype.method = function () {
//...
};
 
J

Josh Russo

Just rewrite it in a proper way.

var Widget = (function () {
  function onClick(evt) {
    //...
  }

  return function (widgetId) {
    this.myfield = document.getElementById(widgetId);

    util.addListener(this.myfield, 'click', onClick);
  };

})();

/**
 * Do something with `myfield' member
 */
Widget.prototype.method = function () {
  //...



};

Yes, I have started using the above pattern for creation of user
objects. I still need to understand the mechanics of prototyping more,
but this thread was me just trying to solidify my understanding of why
the previous pattern was bad.

Once I hit the point in this thread that I really understood what
needed to be looked for, a review of my code found none of the
patterns I thought I had created. My simplified example didn't
actually exist in the many different way my object creation patterns
have evolved. Go figure.
 
J

John G Harris

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. You have
said, I seem to remember, that there are no singleton objects in JS, so
every object must be one of many somethings.


I would have called it an Array object.

You are using 'Array' as an adjective here. This is just a short way of
saying that it's an object that was created by the constructor named
Array.

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

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.

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.


John
 
G

Gregor Kofler

Am 2010-07-22 15:48, Josh Russo meinte:
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?

You are passing a reference, but it will not get "merely stored".
Instead it will be wrapped and fiddled with by jQuery (for cross-browser
"normalization" and such stuff).
var X = [];
var Y = [];

Bad form? :) But seriously, the X and Y variables refer to Array
objects.

Why is this bad form?

It is recommended to use upper case variable names for constructor
functions only.
I always want to know how things really work and in that it helps to
speak the language so everyone is on the same page.

With this attitude, you will never become a good script kiddie...

Gregor
 

Ask a Question

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

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

Ask a Question

Members online

Forum statistics

Threads
473,990
Messages
2,570,211
Members
46,796
Latest member
SteveBreed

Latest Threads

Top