473,883 Members | 2,141 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

How do I properly pass a parameter to a parameterized event handler in a loop?

I have the following HTML file that I've been using for testing...

<html>
<head>
<script type="text/javascript">
<!--
function handleWindowLoa d() {
var items = [];
for (var i = 0; i < 11; i++) {
items[i] = "item" + (i + 1);
}

var parent = document.getEle mentById("paren t");
for (var i = 0; i < items.length - 1; i++) {
var child = document.create Element("div");
child.innerHTML = items[i];
var currentItem = items[i];
handler = new Object();
handler.current Item = currentItem;
handler.onclick = function() {
handleButtonCli ck.call(handler );
}
child.attachEve nt('onclick', handler.onclick );
parent.appendCh ild(child);
}
}
window.onload = handleWindowLoa d;

function handleButtonCli ck() {
alert(this.curr entItem);
}
//-->
</script>
</head>
<body>
<div id="parent">
</div>
</body>
</html>

What I want is for the handleButtonCli ck function to show an alert with the
text "item1", "item2", and so forth for each of the items clicked by the
user. Instead, it shows "item10" for every child of the parent element.
But I don't understand why. I thought that the code would be creating a
closure (am I using this term correctly?) for each child element, but it
apparently is not. Can anyone provide me with a solution that can clear up
my confusion?

I have also read that closures are bad from the point of view that they can
often be the cause of memory leaks. Is there a memory-leak-less way to
achieve the same thing that as the code above?

Thanks for your time.
Dec 29 '05 #1
10 2525
On 2005-12-29, Sean Dockery <do*********@gm ail.com> wrote:
I have the following HTML file that I've been using for testing...
function handleWindowLoa d() {
var items = [];
for (var i = 0; i < 11; i++) {
items[i] = "item" + (i + 1);
}

var parent = document.getEle mentById("paren t");
for (var i = 0; i < items.length - 1; i++) {
var child = document.create Element("div");
child.innerHTML = items[i];
var currentItem = items[i];
handler = new Object();
handler.current Item = currentItem;
handler.onclick = function() {
handleButtonCli ck.call(handler );
} if(child.attach Event)
child.attachEve nt('onclick', handler.onclick );
else
child.onclick=h andler.onclick; parent.appendCh ild(child);
}
}
window.onload = handleWindowLoa d;

function handleButtonCli ck() {
alert(this.curr entItem);
} What I want is for the handleButtonCli ck function to show an alert with the
text "item1", "item2", and so forth for each of the items clicked by the
user. Instead, it shows "item10" for every child of the parent element.
But I don't understand why. I thought that the code would be creating a
closure (am I using this term correctly?) for each child element, but it
apparently is not. Can anyone provide me with a solution that can clear up
my confusion?
you have a closure but your closure refers to the variables of
handleWindowLoa d()
I have also read that closures are bad from the point of view that they can
often be the cause of memory leaks. Is there a memory-leak-less way to
achieve the same thing that as the code above?


get the target object from the event....

Bye.
Jasen
Dec 29 '05 #2
Sean Dockery wrote:
I have the following HTML file that I've been using for testing...

<html>
<head>
<script type="text/javascript">
<!--
Don't use HTML comment delimiters inside script elements, they don't
do anything useful and are potentially harmful.

function handleWindowLoa d() {
var items = [];
for (var i = 0; i < 11; i++) {
items[i] = "item" + (i + 1);
}
This array isn't necessary.


var parent = document.getEle mentById("paren t");
for (var i = 0; i < items.length - 1; i++) {
var child = document.create Element("div");
child.innerHTML = items[i];
var currentItem = items[i];
handler = new Object();
handler.current Item = currentItem;
handler.onclick = function() {
handleButtonCli ck.call(handler );
}
child.attachEve nt('onclick', handler.onclick );
attachEvent is OK for IE and others that copy it's event model, but
what about the rest? Add a fork for addEventListene r for W3C browsers.

But in any case it seems simpler to use:

child.onclick = handler.onclick ;

parent.appendCh ild(child);
}
}
window.onload = handleWindowLoa d;

function handleButtonCli ck() {
alert(this.curr entItem);
}
//-->
</script>
</head>
<body>
<div id="parent">
</div>
</body>
</html>

What I want is for the handleButtonCli ck function to show an alert with the
text "item1", "item2", and so forth for each of the items clicked by the
user. Instead, it shows "item10" for every child of the parent element.
Then set the div id to 'item1', 'item2', etc. and then the
handleButtonCli ck becomes - alert(this.id).

You need to say what is important here. What do you really want to
store, a reference to the new div or the text 'item1', 'item2', etc?

But I don't understand why. I thought that the code would be creating a
closure (am I using this term correctly?) for each child element, but it
apparently is not. Can anyone provide me with a solution that can clear up
my confusion?
You are creating a closure, hence your reference is always to the last
'item' created, not to the one that was attached at the time each div
was created.

As to how to avoid it, there are many schemes but it depends on what
you are really trying to do.

I have also read that closures are bad from the point of view that they can
often be the cause of memory leaks. Is there a memory-leak-less way to
achieve the same thing that as the code above?


Yes, see above. One solution(?) is below:
function handleWindowLoa d()
{
var numOf = 10;
var child, txt;
var parent = document.getEle mentById("paren t");

for (var i=0; i<numOf; ++i) {
child = document.create Element("div");
txt = 'item' + (i + 1);
child.appendChi ld(document.cre ateTextNode(txt ));
child.id = txt;

child.onclick = handleButtonCli ck;
parent.appendCh ild(child);
}
}
function handleButtonCli ck()
{
alert(this.id);
}
window.onload = handleWindowLoa d;


--
Rob
Dec 29 '05 #3

"Jasen Betts" <ja***@free.net .nospam.nz> wrote in message
news:42******** *********@clunk er.homenet...
On 2005-12-29, Sean Dockery <do*********@gm ail.com> wrote:
I have the following HTML file that I've been using for testing...
function handleWindowLoa d() {
var items = [];
for (var i = 0; i < 11; i++) {
items[i] = "item" + (i + 1);
}

var parent = document.getEle mentById("paren t");
for (var i = 0; i < items.length - 1; i++) {
var child = document.create Element("div");
child.innerHTML = items[i];
var currentItem = items[i];
handler = new Object();
handler.current Item = currentItem;
handler.onclick = function() {
handleButtonCli ck.call(handler );
}

if(child.attach Event)
child.attachEve nt('onclick', handler.onclick );
else
child.onclick=h andler.onclick;
parent.appendCh ild(child);
}
}
window.onload = handleWindowLoa d;

function handleButtonCli ck() {
alert(this.curr entItem);
}

What I want is for the handleButtonCli ck function to show an alert with
the
text "item1", "item2", and so forth for each of the items clicked by the
user. Instead, it shows "item10" for every child of the parent element.
But I don't understand why. I thought that the code would be creating a
closure (am I using this term correctly?) for each child element, but it
apparently is not. Can anyone provide me with a solution that can clear
up
my confusion?


you have a closure but your closure refers to the variables of
handleWindowLoa d()


I believe at this point that I can safely say that I don't really understand
what a closure is. I had assumed that they were similar to anonymous inner
classes in Java, but it seems that is not the case.
I have also read that closures are bad from the point of view that they
can
often be the cause of memory leaks. Is there a memory-leak-less way to
achieve the same thing that as the code above?


get the target object from the event....


Can you provide an example?
Bye.
Jasen


Jan 1 '06 #4

"RobG" <rg***@iinet.ne t.auau> wrote in message
news:43******** *************** @per-qv1-newsreader-01.iinet.net.au ...
Sean Dockery wrote:
I have the following HTML file that I've been using for testing...

<html>
<head>
<script type="text/javascript">
<!--
Don't use HTML comment delimiters inside script elements, they don't do
anything useful and are potentially harmful.


I had always believed that they were a considered a "best practice". Can
you give an example of situation where they would be harmful?

function handleWindowLoa d() {
var items = [];
for (var i = 0; i < 11; i++) {
items[i] = "item" + (i + 1);
}
This array isn't necessary.


The array is necessary in that it is the mechanism by which I will be
delivered a number of JavaScript objects. See below.

var parent = document.getEle mentById("paren t");
for (var i = 0; i < items.length - 1; i++) {
var child = document.create Element("div");
child.innerHTML = items[i];
var currentItem = items[i];
handler = new Object();
handler.current Item = currentItem;
handler.onclick = function() {
handleButtonCli ck.call(handler );
}
child.attachEve nt('onclick', handler.onclick );


attachEvent is OK for IE and others that copy it's event model, but what
about the rest? Add a fork for addEventListene r for W3C browsers.


This is just a proof of concept. In production, I'm using the popular
"addEvent" function that hides the browser details.
But in any case it seems simpler to use:

child.onclick = handler.onclick ;

parent.appendCh ild(child);
}
}
window.onload = handleWindowLoa d;

function handleButtonCli ck() {
alert(this.curr entItem);
}
//-->
</script>
</head>
<body>
<div id="parent">
</div>
</body>
</html>

What I want is for the handleButtonCli ck function to show an alert with
the text "item1", "item2", and so forth for each of the items clicked by
the user. Instead, it shows "item10" for every child of the parent
element.
Then set the div id to 'item1', 'item2', etc. and then the
handleButtonCli ck becomes - alert(this.id).

You need to say what is important here. What do you really want to store,
a reference to the new div or the text 'item1', 'item2', etc?


Okay. In my application, I have a list (array) of JavaScript objects that
are being provided through the DWR remoting library. For the purposes of
testing, I could easily create the objects as follows...

var person0 = { id: 1234, firstName: 'John', lastName: 'Doe' };
var person1 = { id: 2345, firstName: 'Jack', lastName: 'Rabbit' };
var people = [person0, person1];

In the callback function, I want to create HTML elements in the DOM for each
of the items in the result list such that the elements that allow for
addition detail information to be fetched for each person when the user
clicks on them. I want the handleButtonCli ck function in my example to have
access to the relevant object which was clicked upon by the user.
But I don't understand why. I thought that the code would be creating a
closure (am I using this term correctly?) for each child element, but it
apparently is not. Can anyone provide me with a solution that can clear
up my confusion?


You are creating a closure, hence your reference is always to the last
'item' created, not to the one that was attached at the time each div was
created.


As I mentioned in the other reply in this thread, I have come to believe
that I don't understand closures yet. I had thought that they worked the
same as Java's anonymous inner classes, but they do not.

As to how to avoid it, there are many schemes but it depends on what you
are really trying to do.

I have also read that closures are bad from the point of view that they
can often be the cause of memory leaks. Is there a memory-leak-less way
to achieve the same thing that as the code above?
Yes, see above. One solution(?) is below:
function handleWindowLoa d()
{
var numOf = 10;
var child, txt;
var parent = document.getEle mentById("paren t");

for (var i=0; i<numOf; ++i) {
child = document.create Element("div");
txt = 'item' + (i + 1);
child.appendChi ld(document.cre ateTextNode(txt ));
child.id = txt;

child.onclick = handleButtonCli ck;
parent.appendCh ild(child);
}
}
function handleButtonCli ck()
{
alert(this.id);
}


I'm confused by this part here. Can you tell me to which JavaScript object
the keyword "this" refers in this function? I am confused because I thought
that the "this" keyword was only value when you did something like this...

function MyObject(id) {
this.id = id;
}
myObject.protot ype.whatever = function() {
alert(this.id);
}
var myObj = new MyObject(567);
myObj.whatever( );

....and that the "call" method of the Function object was the only way to
bind the "this" keyword to a specific object when dealing with generic
methods. For example...

function MyObject(id) {
this.id = id;
}

function whatever() {
alert(this.id);
}

var myObj = new MyObject(678);
whatever.call(m yObject);

Is there always a value for the "this" keyword that is implied somehow?
window.onload = handleWindowLoa d;
--
Rob

Jan 1 '06 #5
Sean Dockery wrote:
I have the following HTML file that I've been using for testing...

<html>
That is not Valid HTML. <URL:http://validator.w3.or g/>
<head>
<script type="text/javascript">
<!--
Trying to comment out `script' element's content is unnecessary and
potentially harmful. In contrast your assumption, it is not at all
best practice, it is rather the practice of the uninitiated and the
incompetent. Since you already asked why, I can refer you here to
previous discussions; Google (Groups) is your friend. [psf 6.1]
function handleWindowLoa d() {
var items = [];
for (var i = 0; i < 11; i++) {
items[i] = "item" + (i + 1);
}

var parent = document.getEle mentById("paren t");
for (var i = 0; i < items.length - 1; i++) {
var child = document.create Element("div");
child.innerHTML = items[i];
This is all error-prone.

<URL:http://pointedears.de/scripts/test/whatami#inferen ce>
var currentItem = items[i];
handler = new Object();
handler.current Item = currentItem;
handler.onclick = function() {
handleButtonCli ck.call(handler );
}
child.attachEve nt('onclick', handler.onclick );
Frankly, I do not understand why you just not make direct use of the
means the DOM provides in the first place.
parent.appendCh ild(child);
}
}
window.onload = handleWindowLoa d;
That will be called when the window has finished loading. That is not
necessarily when the document it displays has finished loading. Use
the `onload' attribute of the HTML document's `body' element instead;
images and objects may not be loaded by then, but iff there is a DOM
tree, it is then there for you to use it along with its element objects.
function handleButtonCli ck() {
alert(this.curr entItem);
}
//-->
</script>
</head>
<body>
<div id="parent">
</div>
</body>
What are users without enabled client-side script support going to do with
that "document"? Client-side scripting should be used to extend documents,
not to build them, unless those documents can only be accessed through
scripting (which required some search engine and code tweaks). Graceful
degradation is the keyword here.
</html>

What I want is for the handleButtonCli ck function to show an alert with
the text "item1", "item2", and so forth for each of the items clicked by
the user. Instead, it shows "item10" for every child of the parent
element. But I don't understand why.

I thought that the code would be creating a closure (am I using this term
correctly?) for each child element, but it apparently is not. Can anyone
provide me with a solution that can clear up my confusion?


The closure created by the method assignment is unused because you are
passing a reference to handler's method to the method that assigns the
event listener [currently attachEvent()]. When you do this, the Function
object referred to is not longer called as method of the object `handler'
refers to but as method of the Global Object -- it loses its connection to
its previous owner. `handler' within the method code will then no longer
refer to the value `handler' had when the function object was created and
assigned a method of `handler', but to the last value of the global
`handler' variable; that is, the value it is assigned in the last loop.

A possible workaround is

child.attachEve nt(
'onclick',
function()
{
handler.onclick ();
});

The same problem occurs and the same workaround is suggested, e.g., when you
use a reference to a named method as first argument of the setTimeout() or
setInterval() methods of Window objects; see previous discussions.
HTH

PointedEars
Jan 1 '06 #6
On 2005-12-31, Sean Dockery <do*********@gm ail.com> wrote:
I have also read that closures are bad from the point of view that they
can
often be the cause of memory leaks. Is there a memory-leak-less way to
achieve the same thing that as the code above?


get the target object from the event....


Can you provide an example?


not a good one, I have one script that uses an event handler on the container
and then from that event determines which contained object owns the event

but it has a number of limitations (probably only works with images)
--

Bye.
Jasen
Jan 1 '06 #7
Sean Dockery wrote:
"RobG" <rg***@iinet.ne t.auau> wrote in message
news:43******** *************** @per-qv1-newsreader-01.iinet.net.au ...
Sean Dockery wrote:
I have the following HTML file that I've been using for testing...

<html>
<head>
<script type="text/javascript">
<!--
Don't use HTML comment delimiters inside script elements, they don't do
anything useful and are potentially harmful.

I had always believed that they were a considered a "best practice". Can
you give an example of situation where they would be harmful?


HTML comment delimiters were used inside script elements to cater for
browsers that didn't know what a script element was and to stop them
displaying the element content. Such browsers would be prior to
Netscape 2 (Dec 1995), IE 3 (Jun 1996) or HTML 3.2 (Jan 1997).

Anyone still using one of those browsers on the web today has far more
to worry about than the display of some script element content. If
that is a genuine concern for you, put the script in an external file
so that the script element has no content.

Even if someone visited your site with such an old browser, it should
not display markup appearing inside the head element anyway.

The delimiters are potentially harmful for two reasons:

1. They are not valid JavaScript (or ECMAScript) and browsers are not
required to treat them as comment delimiters (though likely all
current browsers do provided they start before any real script and the
closing tag is commented out).

2. If you decide to use XHTML, the script element is not portable as
the comment delimiters will comment out the script content. XHTML
requires that different delimiters be used:

<URL:http://www.w3.org/TR/xhtml1/#h-4.8>
Again, I think most browsers will ignore them but you can't guarantee
that.

In reality, adding comment delimiters does no real harm in current
browsers, but the fact that they have survived for at least 5 years
(or so) beyond their use-by date hints that their continued use simply
perpetuates their futile existence.

Welcome to 2006 :-)

function handleWindowLoa d() {
var items = [];
for (var i = 0; i < 11; i++) {
items[i] = "item" + (i + 1);
}


This array isn't necessary.

The array is necessary in that it is the mechanism by which I will be
delivered a number of JavaScript objects. See below.


Ah, a prototype. :-)

var parent = document.getEle mentById("paren t");
for (var i = 0; i < items.length - 1; i++) {
var child = document.create Element("div");
child.innerHTML = items[i];
var currentItem = items[i];
handler = new Object();
handler.current Item = currentItem;
handler.onclick = function() {
handleButtonCli ck.call(handler );
}
child.attachEve nt('onclick', handler.onclick );


attachEvent is OK for IE and others that copy it's event model, but what
about the rest? Add a fork for addEventListene r for W3C browsers.

This is just a proof of concept. In production, I'm using the popular
"addEvent" function that hides the browser details.


I can guess what that does, but adding the onclick directly as below
seems simplest of all.

But in any case it seems simpler to use:

child.onclick = handler.onclick ;
[...]

You need to say what is important here. What do you really want to store,
a reference to the new div or the text 'item1', 'item2', etc?

Okay. In my application, I have a list (array) of JavaScript objects that
are being provided through the DWR remoting library. For the purposes of
testing, I could easily create the objects as follows...

var person0 = { id: 1234, firstName: 'John', lastName: 'Doe' };
var person1 = { id: 2345, firstName: 'Jack', lastName: 'Rabbit' };
var people = [person0, person1];

In the callback function, I want to create HTML elements in the DOM for each
of the items in the result list such that the elements that allow for
addition detail information to be fetched for each person when the user
clicks on them. I want the handleButtonCli ck function in my example to have
access to the relevant object which was clicked upon by the user.


So you are trying to create a link between the DOM object and the
'record' in the array. I think the easiest way is to pick a unique
identifier for each record (you have an id that might be useful) then
use that as the key to the person record.

When you create each div, give it an id that you use as the key to the
person's record in the people object. IDs can't start with numbers
but can include them. The example below (end of post) does just that.

I've used an array of for the people records then created an index
object that maps the element IDs to the people record indexes. That
may be useful, but you can also just sift through the records in an
object using for..in for up to say, 50 records with no noticeable
affect on performance (depending on the system). If you have a lot of
records, an index will really help.

The people array could be an object too, I'm not really using the
array-ness of it. If the ID is unique, the structure could be:

var people = {
'1234' : {firstName: 'John', lastName: 'Doe' },
'2345' : {firstName: 'Jack', lastName: 'Rabbit'}
};

Using an array means that if you modify the order of records, delete
or add some you'll have to update the index object.

[...]

As I mentioned in the other reply in this thread, I have come to believe
that I don't understand closures yet. I had thought that they worked the
same as Java's anonymous inner classes, but they do not.
I don't know what Java anonymous inner classes are, and while I can
recognise a closure I can't explain them fully. They are powerful and
handy but can also cause problems.

As to how to avoid it, there are many schemes but it depends on what you
are really trying to do.
I have also read that closures are bad from the point of view that they
can often be the cause of memory leaks. Is there a memory-leak-less way
to achieve the same thing that as the code above?
Yes, see above. One solution(?) is below:
function handleWindowLoa d()
{
var numOf = 10;
var child, txt;
var parent = document.getEle mentById("paren t");

for (var i=0; i<numOf; ++i) {
child = document.create Element("div");
txt = 'item' + (i + 1);
child.appendChi ld(document.cre ateTextNode(txt ));
child.id = txt;

child.onclick = handleButtonCli ck;
parent.appendCh ild(child);
}
}
function handleButtonCli ck()
{
alert(this.id);
}

I'm confused by this part here. Can you tell me to which JavaScript object
the keyword "this" refers in this function?


When the function is attached to an element using a reference, 'this'
will refer to the element whose event called the function. In the
case above, 'this' will refer to the div that was clicked on.

I am confused because I thought
that the "this" keyword was only value when you did something like this...

function MyObject(id) {
this.id = id;
}
myObject.protot ype.whatever = function() {
alert(this.id);
}
var myObj = new MyObject(567);
myObj.whatever( );
In the above case, 'this' refers to the new object being created.


...and that the "call" method of the Function object was the only way to
bind the "this" keyword to a specific object when dealing with generic
methods. For example...

function MyObject(id) {
this.id = id;
}

function whatever() {
alert(this.id);
}

var myObj = new MyObject(678);
whatever.call(m yObject);

Is there always a value for the "this" keyword that is implied somehow?


If it doesn't apply to anything else, it will be a reference to the
global object (the window object in most browsers).
Maybe something like this will do the trick (feature detection and
doctype omitted for brevity):
<html>
<head><title>.. .</title>
<script type="text/javascript">

// A people array that holds records for each person
var people = [
{ id: 1234, firstName: 'John', lastName: 'Doe', age: 35 },
{ id: 2345, firstName: 'Jack', lastName: 'Rabbit', age: 12 }
];

// To hold a reference to each people record by id:
var peopleIndex = {};

function handleWindowLoa d()
{
var parent = document.getEle mentById("paren t");
var d, p, pName;
for (var i=0, len=people.leng th; i<len; ++i){

// Create a div element
d = document.create Element('div');

// Build a text string and add it as div content
pName = people[i].firstName + ' ' + people[i].lastName;
d.appendChild(d ocument.createT extNode(pName)) ;

// Use the person ID to give the div element an id
d.id = 'id-' + people[i].id;

// Add a cross-reference entry in the index file for faster
// retrieval of the person record later
peopleIndex['id-' + people[i].id] = i;

// Add the onclick
d.onclick = function (){
handleButtonCli ck(this.id, people, peopleIndex);
}

parent.appendCh ild(d);
}
}

function handleButtonCli ck(elId, obj, objIndex)
{
var idxNum = objIndex[elId];
var record = obj[idxNum];
var txt = 'Record ' + idxNum;
for (var prop in record){
txt += '\n' + prop + ' : ' + record[prop];
}
alert(txt);
}

window.onload = handleWindowLoa d;

</script>
</head>
<body>
<div id="parent"></div>
</body>
</html>

--
Rob
Jan 1 '06 #8
On 01/01/2006 00:19, Sean Dockery wrote:

[snip]
I had always believed that [SGML comment declarations in scripts]
were a considered a "best practice". Can you give an example of
situation where they would be harmful?
To say that they are potentially harmful, whilst theoretically true (as
Rob explained), can be detrimental to the case because it's hard to
prove (at least with HTML). Irrespective of that, they are /not/ best
practice, and haven't been for a long time.

[snip]
[...] I have come to believe that I don't understand closures yet. I
had thought that they worked the same as Java's anonymous inner
classes, but they do not.
Closures in ECMAScript are a fairly simple concept but the deeper
mechanics, which do need to be understood to use closures effectively,
are much more complex.

We begin with nested functions.

function outer(argument) {
var local;

function inner() {
}
}

As you are no doubt aware, nested functions have access to all local
variables (including formal arguments and other nested functions) of the
enclosing function object. Under normal circumstances, returning from
the outer function will cause the inner function to be destroyed (there
will be no references to it, so it will be garbage collected like any
other object).

A closure is formed when a nested function survives after the enclosing
function has returned. This can be achieved by either returning a
reference to the nested function, or by assigning that reference to a
variable.

function outer() {
function inner() {
}

return inner;

/* or:
*
* return function() {
* };
*/
}
var myClosure;

function outer() {
function inner() {
}

myClosure = inner;

/* or:
*
* myClosure = function() {
* };
*/
}

What's special about closures is that the local variables that could be
accessed still can be; they survive just as the inner function does.

A more in-depth explanation can be found in the FAQ notes[1].

[snip]
Is there always a value for the "this" keyword that is implied
somehow?


Yes. There are four scenarios in which the this operator value changes.

The new operator:

When the new operator is used, an object is created, the
prototype property of the function reference operand is added
(if it's an object) to the prototype chain of the new object,
and the function object is then called with the this operator
referring to the newly created object.

var object = new MyObject();

1. Create a new object.
2. If the prototype property of MyObject is an object,
assign it to the internal [[prototype]] property of the
object in (1).
3. Call MyObject, using a reference to the object in (1) as
the value of the this operator.
4. If the return value of MyObject is an object reference,
assign that to the variable, object. Otherwise assign a
reference to the object in (1).

The Function.protot ype.apply and call methods:

These two methods allow a function to be called with any
arbitrary object as the this operator value. If the first
argument is null or undefined, the this operator value will
refer to the global object.

var myObject = { myMethod : function() {return 'object';} },
myMethod = function() {return 'global';};

function myFunction() {
alert(this.myMe thod());
}

myFunction.call (myObject); /* 'object' */

myFunction.call (); /* 'global' */
/* or:
*
* myFunction.call (null);
*/

Methods:

When a function is called as a member of some object, using
either dot or square bracket notation, the this operator will
reference that object. A method can also be transferred from
one object to another, and the this operator will refer to that
new object.

var A = { myMethod : function() {alert(this.ide ntifier);},
identifier : 'A' },
B = { identifier : 'B' };

B.myMethod = A.myMethod;
A.myMethod(); /* 'A' */
B.myMethod(); /* 'B' */

What is important to note here is that the this operator value
is determined by /how/ a function is called. This will become
very important in the next (and final) section.

The global and activation/variable objects:

All variables are properties of some object, including global
and local variables. Global variables are properties of the
global object. Local variables are properties of the variable
object: an object that sits at the top of the scope chain of
each and every function, and therefore first encountered when
resolving identifiers. If an identifier resolves to a property
of one of these objects, the this operator value will refer to
the global object.

var global = this; /* The this operator also refers to the
* global object in global scope.
*/

function myFunction() {
alert(this == global);
}
function outer() {
function inner() {
alert(this == global);
}
inner();
}

myFunction(); /* true */
outer(); /* true */

Hope that helps,
Mike
[1] <http://www.jibbering.c om/faq/faq_notes/closures.html>

--
Michael Winter
Prefix subject with [News] before replying by e-mail.
Jan 1 '06 #9
Thanks go out to Jasen Betts, RobG, and Michael Winter for their supportive
responses in helping me to understand how closures work in JavaScript. I
had an "a ha" moment on Sunday, and I think that I get them now.

Thanks especially to Michael Winter for his superb explanation and examples.
I am very grateful for the time that you must have put into composing your
response.

Here is my solution, for anyone who is interested...

<html>
<head>
<script type="text/javascript">
<!--
function ClickHandler(pe rson) {
this.person = person;
}
ClickHandler.pr ototype.attach = function(child) {
var that = this;
child.attachEve nt('onclick', function() { that.onclick(); });
}
ClickHandler.pr ototype.onclick = function() {
alert(this.pers on.firstName + ' ' + this.person.las tName + ' with id = '
+ this.person.id + ' was clicked');
}
function handleWindowLoa d() {
var person0 = { id: 123, firstName: 'John', lastName: 'Doe' };
var person1 = { id: 245, firstName: 'Jack', lastName: 'Rabbit' };
var person2 = { id: 345, firstName: 'Mary', lastName: 'Lamb' };
var people = [ person0, person1, person2 ];
var parent = document.getEle mentById("paren t");
for (var i = 0; i < people.length; i++) {
var person = people[i];
var child = document.create Element("div");
child.innerHTML = person.firstNam e + ' ' + person.lastName ;
var handler = new ClickHandler(pe rson);
handler.attach( child);
parent.appendCh ild(child);
}
}
window.onload = handleWindowLoa d;
//-->
</script>
</head>
<body>
<div id="parent">
</div>
</body>
</html>


"Michael Winter" <m.******@bluey onder.co.uk> wrote in message
news:1w******** ***********@tex t.news.blueyond er.co.uk...
On 01/01/2006 00:19, Sean Dockery wrote:

[snip]
I had always believed that [SGML comment declarations in scripts] were a
considered a "best practice". Can you give an example of situation where
they would be harmful?


To say that they are potentially harmful, whilst theoretically true (as
Rob explained), can be detrimental to the case because it's hard to prove
(at least with HTML). Irrespective of that, they are /not/ best practice,
and haven't been for a long time.

[snip]
[...] I have come to believe that I don't understand closures yet. I had
thought that they worked the same as Java's anonymous inner classes, but
they do not.


Closures in ECMAScript are a fairly simple concept but the deeper
mechanics, which do need to be understood to use closures effectively, are
much more complex.

We begin with nested functions.

function outer(argument) {
var local;

function inner() {
}
}

As you are no doubt aware, nested functions have access to all local
variables (including formal arguments and other nested functions) of the
enclosing function object. Under normal circumstances, returning from the
outer function will cause the inner function to be destroyed (there will
be no references to it, so it will be garbage collected like any other
object).

A closure is formed when a nested function survives after the enclosing
function has returned. This can be achieved by either returning a
reference to the nested function, or by assigning that reference to a
variable.

function outer() {
function inner() {
}

return inner;

/* or:
*
* return function() {
* };
*/
}
var myClosure;

function outer() {
function inner() {
}

myClosure = inner;

/* or:
*
* myClosure = function() {
* };
*/
}

What's special about closures is that the local variables that could be
accessed still can be; they survive just as the inner function does.

A more in-depth explanation can be found in the FAQ notes[1].

[snip]
Is there always a value for the "this" keyword that is implied
somehow?


Yes. There are four scenarios in which the this operator value changes.

The new operator:

When the new operator is used, an object is created, the
prototype property of the function reference operand is added
(if it's an object) to the prototype chain of the new object,
and the function object is then called with the this operator
referring to the newly created object.

var object = new MyObject();

1. Create a new object.
2. If the prototype property of MyObject is an object,
assign it to the internal [[prototype]] property of the
object in (1).
3. Call MyObject, using a reference to the object in (1) as
the value of the this operator.
4. If the return value of MyObject is an object reference,
assign that to the variable, object. Otherwise assign a
reference to the object in (1).

The Function.protot ype.apply and call methods:

These two methods allow a function to be called with any
arbitrary object as the this operator value. If the first
argument is null or undefined, the this operator value will
refer to the global object.

var myObject = { myMethod : function() {return 'object';} },
myMethod = function() {return 'global';};

function myFunction() {
alert(this.myMe thod());
}

myFunction.call (myObject); /* 'object' */

myFunction.call (); /* 'global' */
/* or:
*
* myFunction.call (null);
*/

Methods:

When a function is called as a member of some object, using
either dot or square bracket notation, the this operator will
reference that object. A method can also be transferred from
one object to another, and the this operator will refer to that
new object.

var A = { myMethod : function() {alert(this.ide ntifier);},
identifier : 'A' },
B = { identifier : 'B' };

B.myMethod = A.myMethod;
A.myMethod(); /* 'A' */
B.myMethod(); /* 'B' */

What is important to note here is that the this operator value
is determined by /how/ a function is called. This will become
very important in the next (and final) section.

The global and activation/variable objects:

All variables are properties of some object, including global
and local variables. Global variables are properties of the
global object. Local variables are properties of the variable
object: an object that sits at the top of the scope chain of
each and every function, and therefore first encountered when
resolving identifiers. If an identifier resolves to a property
of one of these objects, the this operator value will refer to
the global object.

var global = this; /* The this operator also refers to the
* global object in global scope.
*/

function myFunction() {
alert(this == global);
}
function outer() {
function inner() {
alert(this == global);
}
inner();
}

myFunction(); /* true */
outer(); /* true */

Hope that helps,
Mike
[1] <http://www.jibbering.c om/faq/faq_notes/closures.html>

--
Michael Winter
Prefix subject with [News] before replying by e-mail.

Jan 3 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
21652
by: Zlatko Matiæ | last post by:
Let's assume that we have a database on some SQL server (let it be MS SQL Server) and that we want to execute some parameterized query as a pass.through query. How can we pass parameters to the server ? Is it possible to use parameters in pass-through queries ? An additional question: Is it possible to connect to a database on MySQL or PostgreSQL using ADO ? Is it possible to execute pass-through queries with parameters, using ADO...
8
3372
by: Brian F | last post by:
Exactly what the subject says. I have an ASP page that I want my C# windows application to open in Internet Explorer, and if possible have it send along a list of values from a list box. Thank you.
7
2077
by: liyang3 | last post by:
Hi, I have Class A, B and C. Class A has an instance of B. Class B has an instance of C. In the instance of C, it generates some data that need to be passed back to Class A. But Class C doesnot know anything about Class A. I'm dealing with legacy code. What is the best way to implement it and have the code change to existing classes such as A and B small? Any
2
2503
by: Ronnie Smith | last post by:
I am trying to pass a function (method) address to a user control to associate with an event. The small user control which sends events is contained in a larger user control group which is in turn contained in the main application. I need the event handler to exist at this top level in the application, and so I'm trying to somehow let the small control (two layers down) know the address of this handler, so that the function is called. ...
1
7764
by: | last post by:
Hi, I've defined an ObjectDataSource and a parameterized DataSet. I would like it if I could pass the parameter value that describes the query that creates the DataSet as part of a user control declaration. Here's how the parameter is described in the context of my ObjectDataSource: <asp:ObjectDataSource ID="ObjectDataSource1" runat="server" SelectMethod="GetArticlesByWhomever" TypeName="WhateverTableAdapters.WhateverTableAdapter">
3
4784
by: r_o | last post by:
hi all, i'm trying to dynamically assign an event handler for an onmouseover event on a <Li> element. i need to pass the event as a parameter to the handler as follows <script language="javascript"> newLi=document.createElement("li") newLi.onmouseover=bulkVal( ' some string ',event) but i cant get it to work in FF1 in IE6 it works but the event fires before the mouse is over the element, it fires once and that's it no more.. i know...
2
8527
by: | last post by:
I have a gridview with a textbox in an ItemTemplate, as below. The OnTextChanged event fires okay but how do I pass a parameter to it, I get an error when I try "OnTextChanged(""SomeData"")". I would also like to pass in the value of column 1. I would also like to be able to get the row the user is on when this event fires. Thank you for your help. <asp:GridView ID="gv" /> <Columns> <asp:BoundField DataField="Col1"...
6
2085
by: Max | last post by:
i have a event bind function like this(though it is not so robust): bind$=function(o,evt,fn,cb){ var aE='attachEvent'; var aEL='addEventListener'; if(!o&&o){ return o(evt,fn,!!cb); } return o('on'+evt,fn); };
24
55286
by: =?Utf-8?B?U3dhcHB5?= | last post by:
Can anyone suggest me to pass more parameters other than two parameter for events like the following? Event: Onbutton_click(object sender, EventArgs e)" Event handler: button.Click += new EventHandler(Onbutton_click); I want to pass more information related that event. & want to use that
0
9798
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
11164
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
10864
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9588
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7980
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5807
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
6008
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4623
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
4230
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.