David said:
Which is below where I asked the question about the code above.
It was unclear to me what you were after. I posted a more detailed
explanation later.
l = ahrefs.length;
while (l--) {
ahrefs[l].href = '#';
ahrefs[l].tabIndex = 0;
ahrefs[l].onclick = (function(j) { return function()
{ global.alert(j); return false; }; })(l + 1);
And there.
Wherever possible, assigning a function expression that forms a
circular reference should be avoided else IE's famous memory leak
becomes an issue. This particular form effectively breaks the closure
with i, but creates an additional execution object on the scope chain
that exacerbates the leak.
This can be avoided by setting ahrefs to null at the end. It was an
oversight that I left this out.
It breaks the cirulcar reference (and hence a common cause of memory
leaks) but not the closure that each function expression assigned as
Of course it doesn't "break" the closure. I don't know what that
means and the closures are necessary for the example.
No, they aren't. In fact breaking the closure to i is what this thread
is all about. The closure with the outer function is a by-product of
the function expression assignment and is a bit of a nuisance here.
I don't see that at all. Closures are not inherently leaky. That is
a myth that was spread by Microsoft because they didn't understand why
their own code leaked.
The closure makes the circular reference possible, so it's good to not
create them if they aren't needed. That doesn't mean to say they are
inherently bad, just that the OP should be aware.
[...]
2. Assign the handler outside the scope of the main function like:
assignHandler(element, event, functionRef [, paramArray]);
Then you have to rely on Function.prototype.apply,
Not necessarily, the OP's example does not require it so "it's not an
issue in this case".
I don't know what you mean. Do you have an example of this
hypothetical assignHandler function that handles arguments (as the OP
requires) and does not use use call or apply?
I'm sure you can do it, but that you are currently thinking of a general
function that will handle every case. If there is no need to set the
handler's this keyword to the element, and if you know how many
arguments will be called, then something like the following suits (it
will only work in browsers that support addEventListener, but could
easily accommodate attachEvent also):
<div>
<button id="b0">Button 0</button>
<button id="b1">Button 1</button>
</div>
<script type="text/javascript">
function showArg(id, i){
alert('Button ' + id + ': ' + i);
}
function assignHandler(el, event, fn, arg0, arg1) {
if (el && el.addEventListener) {
el.addEventListener(event,
function(){fn(arg0, arg1)},
false);
}
el = null;
}
(function() {
var button;
var buttons = document.getElementsByTagName('button');
for (var i=0, len=buttons.length; i<len; i++) {
button = buttons
;
assignHandler(button, 'click', showArg, button.id, i);
}
button = null;
buttons = null;
})();
</script>
Now if that were to be a general function, it would need to consider
attachEvent and also probably use call or apply to both set the called
function's this keyword and to pass an unknown number of arguments.
But the OP's case doesn't require it, so such a general function isn't
necessary.
Those are the issues.
A function to do what?
I glanced at that briefly. Looks like a mess to me.
I think Mike would agree, his intention was to show that for the very
small number of browsers in use that require it, it can be done.
3. Use the built-in Function object as a constructor:
ahrefs[1].onclick = new Function('...');
That is an alias for eval.
The use of eval is not necessarily evil, using the built-in Function
Obviously not. There are some rare cases where it is unavoidable and
appropriate.
object as a constructor is perfectly reasonable, though I'm not
suggesting it is always (or even often) the best approach.
All I am suggesting is that it would not be appropriate to use for
code like this example. It is too slow.
It may not be appropriate for many reasons, but I doubt that speed is
one of them.