Skip to main content
Stack Overflow
  1. About
  2. For Teams

Return to Revisions

7 of 11
Updated the username to avoid confusion

First I want to correct Greg: function abc(){} is scoped too — the name abc is defined in the scope where this definition is encountered. Example:

function xyz(){
 function abc(){};
 // abc is defined here...
}
// ...but not here

Secondly, it is possible to combine both styles:

var xyz = function abc(){};

xyz is going to be defined as usual, abc is undefined in all browsers but IE — do not rely on it being defined. But it will be defined inside its body:

var xyz = function abc(){
 // xyz is visible here
 // abc is visible here
}
// xyz is visible here
// abc is undefined here

If you want to alias functions on all browsers use this kind of declaration:

function abc(){};
var xyz = abc;

In this case both xyz and abc are aliases of the same object:

console.log(xyz === abc); // prints "true"

One compelling reason to use the combined style is the "name" attribute of function objects (not supported by IE). Basically when you define a function like this:

function abc(){};
console.log(abc.name); // prints "abc"

its name is automatically assigned. But when you define it like this:

var abc = function(){};
console.log(abc.name); // prints ""

its name is empty — we created an anonymous function and assigned it to some variable.

Another good reason to use the combined style is to use a short internal name to refer to itself, while providing a long non-conflicting name for external users:

// assume really.long.external.scoped is {}
really.long.external.scoped.name = function shortcut(n){
 // let's call itself recursively:
 shortcut(n - 1);
 // ...
 // let's pass itself as a callback:
 someFunction(shortcut);
 // ...
}

In the example above we can do the same with an external name, but it'll be too unwieldy (and slower).

(Another way to refer to itself is to use arguments.callee, which is still relatively long, and not supported in the strict mode.)

Deep down JavaScript treats both statements differently. This is a function declaration:

function abc(){}

abc here is defined everywhere in the current scope:

// we can call it here
abc(); // works
// yet it is defined down there
function abc(){}
// we can call it again
abc(); // works

This is a function expression:

var xyz = function(){};

xyz here is defined from the point of assignment:

// we can't call it here
xyz(); // UNDEFINED!!!
// now it is defined
xyz = function(){}
// we can call it here
xyz(); // works

Function declaration vs. function expression is the real reason why there is a difference demonstrated by Greg.

Fun fact:

var xyz = function abc(){};
console.log(xyz.name); // prints "abc"

Personally I prefer the "function expression" declaration because this way I can control the visibility. When I define the function like that:

var abc = function(){};

I know that I defined the function locally. When I define the function like that:

abc = function(){};

I know that I defined it globally providing that I didn't define abc anywhere in the chain of scopes. This style of definition is resilient even when used inside eval(). While this definition:

function abc(){};

depends on the context and may leave you guessing where it is actually defined, especially in the case of eval() — the answer is: it depends on browser.

Eugene Lazutkin
  • 44k
  • 8
  • 52
  • 57

AltStyle によって変換されたページ (->オリジナル) /