It turns out that wrapping an object in parenthesis not only allows you to manipulate it. Quite literally, the parenthesis provides a wrapper so one can access properties and methods of an object, sometimes in a non-intuitive way:
Number.between = function () {...};
(3).between(2, 5);
A more common application is the use of anonymous functions to provide a scope for variables. This method allows a developer to keep memory clean, by effectively providing an encapsulating block:
(function(){
var x = 12;
alert(x);
})();
Now, straight to the point: Wrapping a function makes it invisible to Firefox, as if the parenthesis themselves provided a "scope". If you try the following code in Firefox and IE, it will fail in Firefox but it will work in IE:
(function testme(){
alert('success!');
})();
testme(); // this will break in Firefox
In my uneducated opinion, the parenthesis should only provide a wrapper --a "handle", perhaps-- so that the function can be called immediately after being declared. Since the function was given a name, this name should be available in global scope, but we see this is not the case for Firefox.
Update: As a more versed reader points below, this is due to a different ECMAScript implementation. FX has it right, IE has it wrong. I have to say it's more handy the way IE did it.
Sorry about a late comment, I just stumbled upon this. Firefox is correct according to ECMAscript. It defines two types of functions - function declarations and function expressions.
ReplyDeleteFunction declarations must have a name - which is added to their surrounding scope.
Function expressions can optionally have a name, but this is not added to their surrounding scope. It is available inside the function - so it can make recursive calls, or store variables in the function object, eg.
function foo(f) {
alert(f()); // 1
alert(f.x); // 2
}
foo(function bar() {
bar.x = 2;
return 1;
});
The interpreter decides which type of function is declared by its context - if the keyword function is the first token of a statement it's a function declaration, otherwise it's a function expression. This is why the brackets indicate that the function is an expression. Another way to write your example:
+function testme(){
alert('success!');
}();
testme(); // this will break in Firefox
Here, the unary plus prevents the function from being a declaration.
But, as you've observed, different browsers implement this differently. Safari and Konqueror often refuse to parse named function expressions, or just ignore the name altogether. Which makes named function expressions unusable - a pity as they can be useful.
@Daniel: Thx for the comment! Late comments are much better than no comments.
ReplyDeleteThere are two situations where I have used named function expressions.
1. When including a script that modifies the BODY element, which can make IE crash:
(function foo(){
if(!document.readyState ||
document.readyState == 'complete'){
document.body.appendChild(someNode);
} else { setTimeout(foo, ); })();
There's clearly much better ways to achieve this, so I'll move on to the second example
2.When declaring methods for a constructor, so I can see the stack in the debugger:
function Foo(){
this.bar = function bar(){};
}
When I see the stack in MSDE, instead of a bunch of anonymous functions, I'll see "bar".