My JavaScript book is out! Don't miss the opportunity to upgrade your beginner or average dev skills.

Sunday, October 11, 2009

Named function expressions demystified II

Update If after this reading things are still the same, please read the part 3 of this post, thanks.


I have been criticized just for fun and in a impulsive way without analysis or tests (I am not talking about Juriy who gently replied with interesting points in the part 1 of this post - and I replied back).
First of all, if the purpose of an article is to describe a behavior and provide a solution, there should not be any challenge or run for the copyright ... we are developers, and we want the best solution, for us and others, if this solution has been published.

Specially for a complicated language as JavaScript is, Virtual Machine and cross browser troubles speaking, is really difficult, sometimes impossible, to find the ultimate and perfect solution, so let's keep the argument in a professional way, agree?

What Is Wrong With Juriy Solution

Somebody does not get it, and it could be my fault. So this is about inconsistencies, and I'll show you Juriy code to avoid any kind of misunderstanding, OK?

var fn = (function(){

// declare a variable to assign function object to
var f;

// conditionally create a named function
// and assign its reference to `f`
if (true) {
f = function F(){
// now try to create a setTimeout here
// assuming we need it

// error, there is no F reference
// anymore in this context.
// This function obviously exists and
// the entire point is to find a solution
// to replace arguments.callee
// so do you think is a good design
// we cannot use the function name
// with every browser?
setTimeout(F, 1000);

// insted we have to use another name
// but there is NO REASON to do this
// if you understood my precedent post
setTimeout(f, 1000);

// so the purpose is to make function
// call possible via name and the solution
// is to do not use the function name
// am I the only one spotting
// inconsistency here?

alert(f == F); // FALSE
// because F was the last option
// and F has been referenced to null
}
}
else if (false) {
// same as above
f = function F(){ }
}
else {
// same as above
f = function F(){ }
}

// Assign `null` to a variable corresponding to a function name
// This marks the function object (referred to by that identifier)
// available for garbage collection
var F = null;

// NO, this does not mark anything
// this is another layer in JScript
// the function exists, as exists the last one
// if we are nullify a reference, the garbage
// will discard the function because not
// referenced ANYWHERE in this contest

// This behavior is EXACTLY THE SAME
// if we have last option callback
// in IE since the last function reference
// will be the only one, then other functions
// will be collected

// Moreover, with "Re Solution"
// the function is trapped in the reference
// where the reference HAS THE SAME NAME
// this means we have THE FUNCTION NAME
// as valid one in the current scope
// NO ALIASES, and garbage is fine


// return a conditionally defined function
return f;
})();


Re Solution

To keep best compatibility the last option could be a bit messy in Opera or old Safari. That is why I have suggested my Re Solution.

var fn = (function(){

// declare the FUNCTION NAME we want to use
var F;

// conditionally create a named function
// and assign its reference to ITS NAME
if (true) {
F = function F(){
// EASY!!!
alert(F == arguments.callee); // TRUE
setTimeout(F, 1000);
}
}
else if (false) {
// same as above
F = function F(){ }
}
else {
// same as above
F = function F(){ }
};

// In this cotext there is
// ONE AND ONLY ONE
// reference to function F
// being the reference evaluated
// AFTER function declaration
// It does not matter if
// there are other functions
// with the same name because
// the reference, which comes after
// WILL POINT TO THAT FUNCTION
// which is a named one

// EASY ???
return F;
})();


As Summary

I hope things are finally clear for everybody. I hope Juriy will get my point, and I am always ready to negate everything I wrote as soon as somebody will demonstrate it is wrong. Again, we are developers, there's no trophy here if we want make something public for developers community.

No comments: