简体   繁体   中英

Assigning a non anonymous function to a variable

In a book I'm reading, there is a page about recursion with the following code:

var hanoi = function hanoi(disc, src, aux, dst){
    if (disc > 0){
        hanoi(disc - 1, src, dst, aux);
        document.writeln('Move disc ' + disc + ' from ' + src + ' to ' + dst);
        hanoi(disc - 1, aux, src, dst);
    }
};

Edit: Question rephrase - In this example, what is the difference between var hanoi = function hanoi(){} and just using var hanoi = function(){} ?

Eg why is Hanoi being declared as the variable, but also the function is being named Hanoi? Why the double up of 'hanoi'?

Firstly, you don't need to name the function. This is sufficient:

var hanoi = function() { /*code*/ }

There, however, is a difference when dealing with variable hoisting and the manner of declaring functions.

For example, the following code will work with no errors:

foo();

function foo(){
   console.log('foo');
}

whereas this will not run:

foo();

var foo = function(){
    console.log('foo');
}

The second example will error out with something like "undefined is not a function".

Function declarations ( function foo() {} ) are hoisted with the full body of the function, while var statements have only the variable hoisted to the top of the scope.

EDIT: Note that there is some wiggle room here:

var hanoi2 = function hanoi() { /*code*/ }

will create two variables hanoi and hanoi2 that both reference the same function. However, hanoi will get hoisted as the full function, but hanoi2 will not.

var hanoi = function hanoi(){} creates a Named Function Expression and assigns it to a variable which name happens to be the same as the expression name.

function hanoi(){} declares a function.

There are difference in the way those two constructs are hoisting. For example you can call declared function before the declaration. But you can't do the same with named function expression.

//ok
var joe = new Person();
function Person() {};

//error
var joe = new Person();
var Person = function Person(){};

It's the difference between a FunctionExpression and a FunctionDeclaration respectively.

  1. In the first case the function is an expression. Why? Only expressions can be assigned to a variable.
  2. In the second case the function is a declaration. Why? It's not used in the context of an expression.

The only noticeable difference is that you can use the FunctionDeclaration before it appears in the current scope. This is because declarations are hoisted in JavaScript. For example:

alert(f()); // Error: undefined is not a function.

var f = function f() { return "Hello World!"; };

Here when we call f the variable f is not yet defined. Hence it throws an error.

alert(f()); // Hello World!

function f() { return "Hello World!"; };

Here we can call f before it appears in the current scope because declarations in JavaScript are hoisted (ie brought to the top of the scope).

Personally I prefer using function declarations instead of function expressions. You can even put function declarations after the return statement in a function and still call them before the return statement. This allows you to write readable modules using the module pattern.

There's a very subtle point at play here. In the following two examples, the body of the function is the same as your original. In one case, an anonymous function is used, while in the other, the function is named "hanoi" just as in the original.

var hanoi2 = function hanoi(disc, src, aux, dst){
  if (disc > 0){
    hanoi(disc - 1, src, dst, aux);
    document.writeln('Move disc ' + disc + ' from ' + src + ' to ' + dst);
    hanoi(disc - 1, aux, src, dst);
  }
};

var hanoi3 = function(disc, src, aux, dst){
  if (disc > 0){
    hanoi(disc - 1, src, dst, aux);
    document.writeln('Move disc ' + disc + ' from ' + src + ' to ' + dst);
    hanoi(disc - 1, aux, src, dst);
  }
};

Will either of these work? Note that the body of the function is still referring to "hanoi", not "hanoi2" or "hanoi3".

It turns out that hanoi2 will work, but hanoi3 will not. This is because when you name a function, the name of the function is available inside the scope of the function body. So, in both your original example and in hanoi2, the "hanoi" inside the function isn't referring to the global variable hanoi but rather the named function hanoi.

So, the answer to your question is that because the function uses recursion, the named version is slightly more robust than the anonymous version under modifications to your code.

In this case, the function will not be hoisted. Hoisting means compiling it before any other code is run. Hoisting is only done to function blocks.

I don't see any reason whatsoever to do this here. You lose hoisting, old versions of IE have memory leaks, and it uses extra bytes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM