All do approximately the same thing, with a few subtle differences:
There is a distinction between the function name and the variable the function is assigned to. The function name cannot be changed, while the variable the function is assigned to can be reassigned. The function name can be used only within the function's body. Attempting to use it outside the function's body results in an error (or undefined
if the function name was previously declared via a var
statement). For example:
var y = function x() {};
alert(x);
The function name also appears when the function is serialized via Function
's toString method.
On the other hand, the variable the function is assigned to is limited only by its scope, which is guaranteed to include the scope in which the function is declared.
As the 4th example shows, the function name can be different from the variable the function is assigned to. They have no relation to each other. A function declaration also creates a variable with the same name as the function name. Thus, unlike those defined by function expressions, functions defined by function declarations can be accessed by their name in the scope they were defined in:
A function defined by 'new Function'
does not have a function name. However, the serialized form of the function shows as if it has the name "anonymous." For example, alert(new Function())
outputs:
Since the function actually does not have a name, anonymous
is not a variable that can be accessed within the function. For example, the following would result in an error:
var foo = new Function("alert(anonymous);");
foo();
Unlike functions defined by function expressions or by the Function
constructor, a function defined by a function declaration can be used before the function declaration itself. For example:
foo();
function foo() {
alert('FOO!');
}
A function defined by a function expression or by a function declaration inherits the current scope. That is, the function forms a closure. On the other hand, a function defined by a Function
constructor does not inherit any scope other than the global scope (which all functions inherit).
var p = 5;
function myFunc() {
var p = 9;
function decl() {
console.log(p);
}
var expr = function() {
console.log(p);
};
var cons = new Function('\tconsole.log(p);');
decl();
expr();
cons();
}
myFunc();
Functions defined by function expressions and function declarations are parsed only once, while those defined by the Function
constructor are not. That is, the function body string passed to the Function
constructor must be parsed each and every time the constructor is called. Although a function expression creates a closure every time, the function body is not reparsed, so function expressions are still faster than "new Function(...)
". Therefore the Function
constructor should generally be avoided whenever possible.
It should be noted, however, that function expressions and function declarations nested within the function generated by parsing a Function constructor
's string aren't parsed repeatedly. For example:
var foo = (new Function("var bar = \'FOO!\';\nreturn(function() {\n\talert(bar);\n});"))();
foo();
A function declaration is very easily (and often unintentionally) turned into a function expression. A function declaration ceases to be one when it either:
- becomes part of an expression
- is no longer a "source element" of a function or the script itself. A "source element" is a non-nested statement in the script or a function body:
var x = 0;
if (x === 0) {
x = 10;
function boo() {}
}
function foo() {
var y = 20;
function bar() {}
while (y === 10) {
function blah() {}
y++;
}
}