"Csaba2000" <ne**@CsabaGabor.com> writes:
for each myCell in the table we can do:
myCell.onresize = function () {
var tmpVar = this;
setTimeout(function() {resizeHandler(tmpVar)}, 20)}
This seems to be working. But I am really suspicious
of that tmpVar. Can someone explain to me whether I'm
getting lucky or whether that tmpVar is safe from being
overwritten if other cells are getting resized.
It is safe.
You declare tmpVar as a local variable. That means that a new variable
is created for each call to the (anonymous) function it lives in.
The inner function expression evaluates to a *closure*. It is a function
value that includes references to all the variables that it uses.
That means that a reference to the local variable survives longer than
the call to the function it lives in. That can be confuzing to people
used to languages like C and C++, where local variables are created on
the stack and removed when the function returns. In this case, it is
just what you need!
I.e. what is that tmpVar bound to?
For each call, it is bound to a new location, and the function inside
is also new each time.
In the interests of better understanding, I'd like to change
the scenario a bit. This time resizeHandler2 only wants to
have handed to it the explicit rowIndex and cellIndex of the
cell that's responsible for its invokation.
So one might imagine the setup proceeding as follows:
for (var i=myTable.rows.length-1;i>=0;i--)
for (var j=myTable.rows[i].cells.length-1;j>=0;j--)
myTable.rows[i].cells[j].onresize = function () {
setTimeout(function () {resizeHandler2(i, j)}, 20)}
This is incorrect, because i and j are not the current values
but rather future values and get passed in as -1 when invoked.
Correct. The inner function contains references to the same instances
of the variables i and j. You can see a variable "x" as a way to
reference a *location*, and that location can contain a *value*.
The function closure remembers the association from variable name
to location, not the value currently in that location. The value
is only looked up when the code containing the variable is executed.
How can I fix this up, so that what I pass in is the i and j
at the time of the function construction and not execution
(without introducing strings. The point being that I want to
know whether I can combine the two approaches)?
You need to create new locations for each inner function. The simplest
(and perhaps the only) way is to put it inside a function. Chang the
last line to:
setTimeout(
function(i,j) {return function () {resizeHandler2(i, j);};}(i,j),
20)}
By wrapping the innner function in another function, we make the i and
j be local variables that are unique to each call. The arguments are
passed as values, so the new variables have the current *values* of
the outer i and j.
We need not call the new variables i and j, they could be called anything:
function(foo,bar) {return function () {resizeHandler2(foo,bar);};}(i,j)
and we could create them with "var" instead of as arguments:
function() {var x=i,y=j;return function (){resizeHandler2(x,y);};}()
The outer function is called immediately, so the code is executed. The
new local variables gets the *values* of i and j. The reference to
these new variables are kept in the returned function.
Behind all of this is the notion of a "lvalue", short for "left value".
How do you evaluate a variable. What is the meaning of "x" in a program.
There are two answers, depending on where "x" occurs, whether it is on
the left or right side of an assignment.
When you write an assignment
x = y;
we have two variables. The one on the left hand side of the assignment
is the variable having its value changed. What happens is:
Find value of right hand side:
Look up "y" in the variable list to find the location it refers to.
Find the value stored in that location.
Look up "x" in the variable list to find the location it refers to.
Store the value from before in that location.
The right hand side is evaluted for its value. The left hand side is
evaluted for its location (it's "l-value"), not its right-value (which
is what we normally call its *value*).
Closures retain the lvalue of a variable.
Hope this helps.
/L
--
Lasse Reichstein Nielsen -
lr*@hotpop.com
Art D'HTML: <URL:http://www.infimum.dk/HTML/randomArtSplit.html>
'Faith without judgement merely degrades the spirit divine.'