26

Possible Duplicate:
JavaScript: var functionName = function() {} vs function functionName() {}
What is the difference between a function expression vs declaration in Javascript?

I am aware of the differences between Function Declarations and Expressions, but have come across this code involving function name and want to understand what happens when we run it:

var abc = function def() {
    console.log("Wait! What??");
}

I know that this is not a way to JavaScript, but just want to know few things:

  1. What happens to abc? Why it works? abc can be called but not def, why?
  2. Is it a function declaration or an expression?
  3. def is undefined - why? If it is supposed to be, are there memory leaks?
  4. Why is abc.prototype is function def?

Thanks

Community
  • 1
  • 1
Om Shankar
  • 7,795
  • 3
  • 30
  • 51
  • 1
    it's a named function expression. `def` can reference itself by using `def` when *inside* the function. Though be aware of browser quirks (IE) – Yoshi Jan 17 '13 at 08:15
  • 1
    You probably haven't read these questions and their answers: http://stackoverflow.com/questions/1140089/how-does-an-anonymous-function-in-javascript-work **and** http://stackoverflow.com/questions/336859/javascript-var-functionname-function-vs-function-functionname – Alvin Wong Jan 17 '13 at 08:16
  • 1
    http://kangax.github.com/nfe/ should have all the answers for you – Bergi Jan 17 '13 at 08:17
  • @AlvinWong, Thanks. I read that but did not read this awesome answer to the second question - http://stackoverflow.com/a/338053/1249219. Since the most voted and accepted one did not explain that – Om Shankar Jan 17 '13 at 08:26
  • 1
    I don't believe this question is a dupe since it is asking specifically about the case where the variable name and function name are different (even though it is answered by one of the answered on one of the other questions). – Jack Jan 17 '13 at 18:04
  • 1
    Its not a duplicate. The questions that have been added to "Possible Duplicate" are for differences in declaration and expression. That's not what has been asked here. Please vote to reopen – Om Shankar Jan 19 '13 at 04:36

5 Answers5

11

What happens to abc?

It contains a function object. If you are doing nothing with it, it will be garbage-collected.

Why it works?

Why not? What "works"?

abc can be called but not def, why?

This is only true from outside, and not in IE. See below.

Is it a function declaration or an expression?

It is a function expression. You can easily see that as it is part of an assignment expression; declarations always need to be on top level (of functions or global code)

def is undefined - why?

Only from outside. A function expression does not create variables. "def" is the name of the function, and inside the function it is a reference to the function as well. This allows recursion for example without using any outer variables.

var abc = function def() {
    def === abc; // true
    def.name; // "def"
}
abc();
def; // undefined

If it is supposed to be, are there memory leaks?

Yes, in Internet Explorer. It creates two distinct functions from that code. For the details, see http://kangax.github.com/nfe/#jscript-bugs

Why is abc.prototype is function def?

It is not. It is just an object. Maybe it is shown with that name in your console, as belongs to a function named "def".

Bergi
  • 513,640
  • 108
  • 821
  • 1,164
  • +1 for covering the "practical" implementation issues (I knew there were some issues, but not *that* many :-/) –  Jan 17 '13 at 08:28
5

It's a named function expression. A possible use for this could be:

var abc = function def() {
    def.test = 'Wait!'; //< sort of a static property
    console.log(def.test+" What??");
}

But beware.

KooiInc
  • 104,388
  • 28
  • 131
  • 164
  • The **beware** link of yours gives much more of information and gives me a huge clarity on the difference. So accepting this answer – Om Shankar Jan 19 '13 at 04:32
2

It is a Function Expression2

Function Expressions can have names as well; the names of Function Expressions are only in scope in the function body1. (Since ECMAScript 5th edition deprecates arguments.callee, this is the only simple way to write a recursive "anonymous" function.)

Because it is a Function Expression, the name may not1 introduce a new binding in the outer scope.

Also, all functions are objects in JavaScript. In f(..), f is evaluated before it is "invoked" with (..); if f did not evaluate to a function then an error is thrown. This is why callbacks, which are just functions, can be named by variables and passed as parameters.

Also, check the assumption/assertion about the prototype:

var abc = function def() {}
abc.prototype === abc // -> false
abc.name              // -> "def"

1 See Bergi's answer.

2 How to easily tell which is which?

The grammar rules only allow function .. to be parsed as a Function Declaration when it is a SourceElement although most engines will still [incorrectly] parse a Function Declaration as a Statement. SourceElement productions only occur at the top-level "block" of a Program or the top-level "block" of a Function.

In any case, whenever there is a function .. that appears in a place that requires an Expression, it will be parsed as a Function Expression. Examples that are all parsed as Function Expressions:

// Can only assign values: Statements do not have values!
var f = function () {}        
var g = function gName () {}  // see Bergi's answer

// Can only pass values: Statements do not have values!
doIt(function () {})          // callback / "anonymous function"

// IIFE: Immediately-Invoked Function Expression
;(function () {})()           // standard IIFE
;(function () {} ())          // alternative standard IIFE
;+function () {} ()           // curious way to write an IIFE
// basically you can use any unary operator to turn it into an expression not only
//  + but also - ! ~ and so on which will modify the return value accordingly

The point is that in every single one of the above cases, function .. appears at a grammar location requiring an Expression and is thus parsed as a Function Expression. (The semicolons at the start of the lines above avoid "ambiguity" with ASI, which is required when writing in a semicolon-free style like I prefer.)

However. ;function () {} () and ;function f () {} () are both invalid syntax - why? ;-)

Christoph
  • 46,101
  • 18
  • 92
  • 121
2

It is a named function expression.

Contrary to Function Declarations the Identifier of a Function Expression is not mandatory.

Your function def is not immediately invoked - the whole function is passed to abc and needs to be invoked explicitely abc().

§13 of the ES5 spec states how named function expressions are built. Read the third production rule on how named function expressions are built.

NOTE The Identifier in a FunctionExpression can be referenced from inside the FunctionExpression's FunctionBody to allow the function to call itself recursively. However, unlike in a FunctionDeclaration, the Identifier in a FunctionExpression cannot be referenced from and does not affect the scope enclosing the FunctionExpression.

All recent browsers handle this correctly, so you don't have to worry about and memory leaks or other weird stuff (the incorrect handling is only in old IE <=8).

Christoph
  • 46,101
  • 18
  • 92
  • 121
1

Your example is a (named) Function Expression.

The difference Between the two is in how the browser loads them.

Function declarations are loaded before any code is executed.
Function expressions are loaded only when the interpreter reaches that line of code.

This means:

abc();
var abc = function() {
    console.log("Wait! What??");
}

Won't work, but:

def();
function def() {
    console.log("Wait! What??");
}

Will.

Now in your example, you can access def, but only inside the function itself.

var abc = function def() {
    console.log(def);
}
abc();

// Logs:
//function def() {
//    console.log(def);
//}
Cerbrus
  • 60,471
  • 15
  • 115
  • 132