0

I am reading the book. Javascript, The good parts by Douglas Crokford. There are examples provided in the book, but I am not able to understand where and how such examples could be useful in practice. I have modified the code here for simplicity. here are two ways, I can do function assignment to a variable.

example1:

var test= function(ex) {
    alert(ex);
};
test(5);

this produces alert box with value of 5

example2:

var test1 = function test2(ex) {
    alert(ex);
};
test1(7); //this produces alert box with value of 7
test2(8)//this does not give a alert box

I have defined function test2 but assigned it to test1. why can't I access test2 directly by calling test2(8). Further I do not see any big advantage in example 2 over example 1. If you there is some difference, and one of them is superior, I would like to hear that.

Thanks

brain storm
  • 25,842
  • 54
  • 187
  • 349
  • you have no function named test2 :( use var test2 = function test2(ex) { alert(ex); }; or test1(8) both will alert. – sharif2008 Jun 18 '13 at 01:02
  • This is nicely explained on [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope#Function_constructor_vs._function_declaration_vs._function_expression). – Vedran Šego Jun 18 '13 at 01:03
  • 1
    Relevant: [JavaScript: var functionName = function() {} vs function functionName() {}](http://stackoverflow.com/q/336859/254830). The style of function declaration you're asking about is explained in [this answer](http://stackoverflow.com/a/338053/254830). – doppelgreener Jun 18 '13 at 01:06
  • @sharif: Iam assigning a function named test2 to a variable test1. so I thought the function test2 exists. Isnt that correct? – brain storm Jun 18 '13 at 01:22
  • @jonathan Hobbs: I have read that link before I posted here. I still do not get why the function named test2 (assigned to test1) does not exist. Its not about anonymous vs named functions. – brain storm Jun 18 '13 at 01:23
  • 1
    @user1988876 Because it doesn't. You never declared it in a way that made it exist beyond the assignment. That's it. – doppelgreener Jun 18 '13 at 01:28

5 Answers5

6
var test1 = function test2(ex) {
    console.log(test2);
};

Naming the function gives it the ability to reference itself from within its body.

test2 is visible only to test2 and its child scopes (functions) if any.

holographic-principle
  • 19,590
  • 10
  • 44
  • 62
  • Note that this syntax will be much more prominent and useful in the future when arguments.callee is phased out (I believe HTML 5 already phased out arguments.callee). The bonus to this is that it is not only forwards compatible but backwards compatible with old browsers as well. – slebetman Jun 18 '13 at 01:13
  • @finishingmove: can you provide me a simple example how can it can be used to reference within itself..That would help me understand better – brain storm Jun 18 '13 at 01:18
  • @bfavaretto: Really? I've used this in browsers as old as Netscape 4 and IE 5. Any references/links as to where it doesn't work? – slebetman Jun 18 '13 at 01:30
5

You're basically assigning a function with a name to test1, what's called a "named function expression". It's useful to debug your code because the name of the function will appear in the call stack trace rather than "anonymous function".

Functions in JavaScript are objects too, so the identifier for the function is test1 (the function object), but the function itself has a name of test2, so test1.name == 'test2'

elclanrs
  • 85,039
  • 19
  • 126
  • 159
  • Thanks. does the function test2 exists? why calling test2(7) does not alert. test1 is assigned a function of test2. but test2 should not cease to exist rite? – brain storm Jun 18 '13 at 01:24
  • I explained above... The function `test2` _is_ the function `test1` with a name of `test2`, So no, `test2` as an identifier doesn't exist. What you're doing is troublesome though; you'd want to assign the same name for the variable _and_ the function: `test2 = function test2(){}` – elclanrs Jun 18 '13 at 01:29
2

The syntax you're referring to is called a named function expression. It is primarily used to support recursion in anonymous functions.

In javascript prior to ECMASCRIPT 5, there are two ways to do recursion when the function is anonymous.

  1. Using arguments.callee:

    (function(x){
        alert(x);
        if (x) {
            arguments.callee(x-1);
        }
    })(10);
    
  2. Using a named function expression:

    (function countdown (x){
        alert(x);
        if (x) {
            countdown(x-1);
        }
    })(10);
    

In ECMASCRIPT 5, when strict mode is enabled arguments.callee is no longer supported. Therefore, in ECMASCRIPT 5 strict mode and for future versions of javascript you should use named function expressions to write recursive anonymous function.


Additional answer:

Now you may be wondering, that's not the syntax you're asking about. That syntax looks like:

(function foo () { foo })()

and you were asking about:

var bar = function foo () { foo }

Actually, they're the same. The named function expression syntax applies to function expressions. Which is nothing more than functions declared in expression context.

In javascript, expression context is simply anywhere math is evaluated. Basically, expression context is anything between braces (), anything to the right of the = sign. And anything which needs to be evaluated by an operator.

Apart from the two forms above, the following are also valid named function expressions:

!function foo(){ foo };

0==function foo(){ foo };

0?0:function foo(){ foo };
slebetman
  • 93,070
  • 18
  • 116
  • 145
1

The way you want it to behave is against the specification. Function declarations must be named, and their name represent variables in the current scope. But function expressions, when named, should not create a variable with their name. Instead, their name becomes available only inside the function.

Some old browsers (e.g. IE8) used to leak the names as variables, see Named function expressions demystified.

bfavaretto
  • 69,385
  • 15
  • 102
  • 145
-1

Your example 2 is not really an example of proper JavaScript. There are two ways to define a function:

  • var foo = function(x) { console.log(x); return x; }

and

  • function foo(x) { console.log(x); return x; }

note that in the first example you are effectively creating an anonymous function first, and then you attach a name ('foo') to that anonymous function object. In the second example, however, you are creating a named function object 'foo' right away.

Also, if you go to console and define first the test2 the way you did it, and then, after it's defined, enter the line var test1 = test2, then you will have both functions available.

You can see the explanation of the deeper technical difference here in another S/O answer, quite upvoted: var functionName = function() {} vs function functionName() {}

Community
  • 1
  • 1
alexakarpov
  • 1,553
  • 1
  • 14
  • 31
  • 1
    It's proper javascript. Specifically it is the only valid syntax in ecmascript 5 strict mode for recursive anonymous functions since arguments.callee is no longer supported – slebetman Jun 18 '13 at 01:29
  • not sure I understand... how is `var test1 = function test2(ex) {...}` an anonymous function? Isn't test2 meant to be the name (and then test1 is an alias for test2)? – alexakarpov Jun 18 '13 at 01:34
  • @alexakarpov It's not an anonymous function, it's a named function expression. – bfavaretto Jun 18 '13 at 01:41
  • that's what I thought; but @slebetman said this syntax (which I thought is improper) -- i.e. `var test1 = function test2(x) {...}` -- is a proper syntax for recursive anonymous function. Hence my question - where's the anonymous function in this example? I am just trying to understand where am I wrong... I'm just learning JavaScript myself, reading the same book as OP, too =) – alexakarpov Jun 18 '13 at 01:44
  • 1
    @alexakarpov: see my answer and bfavaretto's answer. In this syntax the function name is supposed to be treated as anonymous and only visible from within itself (hidden from the rest of the code). But if you read bfavaretto's answer you'll see that some older browsers leak the function name as a local variable. It should be anonymous for all modern browsers. – slebetman Jun 18 '13 at 01:54
  • oh wow.. I see now. had no idea about this _function expression_ vs _function declaration_ business; thanks! – alexakarpov Jun 18 '13 at 02:10