Declared Javascript Functions – Odd Parsing Behavior in IE

Posted in Open Source, Zimbra Web Client by Conrad Daemon on February 2nd, 2007

A function declared in a conditional block that evaluates to false gets defined in IE, but not in Firefox. That is a problem if you are trying to use an ‘ifdef’ or ‘require_once’ mechanism for defining functions. However, if the function is defined via assignment, the reference is not created, which is what you’d expect.


The reason that the unexpected definition is a problem is that declaring a function more than once can have some nasty side effects. Depending on when it happens, your objects can lose type information. Symptoms include methods in the parent class no longer being visible, and unexpected results from ‘instanceof’.

A large project that I’m finishing up is reorganizing the web client to load code dynamically as needed, from packages. Each package consists of a number of files, and each file defines one or more Javascript classes (functions). We need to be careful not to define a class more than once, so our build process surrounds each class definition with an ‘if’ block, using the standard idiom:

if (!defined("Foo")) {
function Foo() {
this.bar = 1;
}
define("Foo");
}

In Firefox, that works as expected. Foo will get defined only once. However, in IE, it will get defined each time the code above is parsed, leading to the side effects described above.

Our current workaround is to define the function via assignment:

if (!defined("Foo")) {
Foo = function() {
this.bar = 1;
}
define("Foo");
}

It seems that the IE parser must be doing a pass where it looks for function declarations and adds them to the symbol table regardless of the containing block. I’m assuming that’s not correct behavior, but I haven’t read the ECMAScript spec thoroughly.

Feel free to try this test page if you want to see it in action.




|  Blog Home

Subscribe


Subscribe by Email



Categories


Archives

  • March 2010
  • February 2010
  • January 2010
  • December 2009
  • November 2009
  • October 2009
  • September 2009
  • August 2009
  • July 2009
  • June 2009
  • May 2009
  • April 2009