50

I'm learning JavaScript at the moment and I don't quite understand when to write a function into a variable.

For instance, both of the following code blocks do the exact same thing in Node.js:

 var onReq = function(req, res) {
   res.write('Hello');
 };

 http.createServer(onReq).listen(3000);

and

function onReq(req, res) {
   res.write('Hello');
 }

 http.createServer(onReq).listen(3000);



Which is the best method to do according to best practices, and why?

imjp
  • 5,557
  • 9
  • 45
  • 58
  • for this question you need more concentration on String variables and integer and float variables; – Sam Arul Raj T Mar 08 '12 at 13:47
  • http://stackoverflow.com/questions/1013385/what-is-the-difference-between-a-function-expression-vs-declaration-in-javascrip – jbabey Mar 08 '12 at 14:06
  • duplicate: http://stackoverflow.com/questions/336859/javascript-var-functionname-function-vs-function-functionname – Gabriel Llamas Mar 08 '12 at 14:12
  • 1
    The second form has the advantage that if for example it's a terribly long function, you can move it to the bottom of the current variable scope to get it out of the way, but still use it higher up. This can come in handy. You can even put it below a final `return` statement, and it'll still work. –  Mar 08 '12 at 14:39

7 Answers7

28

Usually I'll only use a var funcName = function(){} when I would need to redefine the action(s) for that function later on. For example:

var foo = function(a){ return a * 2; }
var bar = foo(2);

foo = function(a){ return a / 2; }

bar = foo(bar);

Otherwise, for most purposes (assuming it's not a callback or a modifier) declaring a function "classically" is usually acceptable.

Brad Christie
  • 96,086
  • 15
  • 143
  • 191
  • I see what you mean, but it's still better to do the former method of declaring function's I've stated right? – imjp Mar 08 '12 at 13:50
14

I default to the non-variable function onReq(){} version. It's not a concious decision I've made, but thinking about it brings forth these arguments:

  • It looks cleaner.
  • It is conceptually simpler: it's just a function, while the other is a function and a variable. It's a small thing, but I find it valuable none the less.
  • It assures me that onReq will always refer to that function body - one less thing to consider when reading the code. Sort of like marking a variable as final in Java.
  • Keeps me from "accidentally" replacing the function, causing unintended side effects elsewhere.
Supr
  • 16,712
  • 3
  • 28
  • 35
3

Here is an explaination:

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).

https://developer.mozilla.org/en/JavaScript/Reference/Functions_and_function_scope

Churk
  • 4,266
  • 5
  • 20
  • 37
  • Just a quick addendum. The function's name in a fn declaration (as MDN uses the term) can be changed - just assign it to a new variable to get another reference to the function. The function name can also be reassigned to another function (or something else entirely) later in the code. Another difference is that a function declaration will hoist the assignment to the top of the scope, whereas using a variable will only hoist the variable's declaration. – meloncholy Mar 08 '12 at 14:12
  • Neither of your points seem correct. For the first one it's a little hard to see what you're saying, but in both cases the variable referencing the function can be reassigned. And the second point isn't right. The function name can be used outside the function body as shown in the question. You're thinking of a named function expression, which is not shown in the question. –  Mar 08 '12 at 14:20
  • Via one of the duplicate links above, kangax's [Named function expressions demystified](http://kangax.github.com/nfe/) covers this in a lot more detail and with a lot more subtlety (e.g. pointed out that my comment on hoisting behaviour can actually vary between browsers). Definitely worth checking out. – meloncholy Mar 08 '12 at 14:36
2

I see that nobody mentioned (directly and practically - which seems this question is about) the reason for which I personally find most useful for storing functions in variables. That reason is dealing with a complex logic that requires a lot of choices (e.g. if's) to determine further course of action for which different functions should be called, possibly with different sets of inputs as well. It makes code cleaner when that further course of action is launched in just one place, at the end of our logic.

function fooA (input) {...};
function fooB (input) {...};
let chosenHandler;
let chosenInput;

// Here we establish which function is relevant
if (someCondition) chosenHandler = fooA;
else chosenHandler = fooB;

// Here we establish which parameter should be used
if (someOtherCondition) chosenInput = 'First input';
else chosenInput = 'Second input';

// Call chosen function with chosen parameters - one place, nice and clean
chosenHandler(chosenInput);

If we tried to call functions directly, the code would get much more messy and get the messier the more complex the logic is.

Eggon
  • 1,045
  • 6
  • 18
1

According to John Resig's JavaScript as a First Language article, your first code block is considered as best practice.

  • 7
    Don't be too influenced by that. There are lots of times where it's much more desirable to use a function declaration, and take advantage of the fact that it is hoisted to the top of your code. Sad that he suggests `// Don't do this: function getData() { }` because it makes it easier to teach functions as an object. Making it easier to teach is a poor reason to start beginners off with the idea that there's something wrong with it. –  Mar 08 '12 at 14:30
1

I personally have encountered certain issues with calling local functions (functions declared inside other functions) when using non-variable syntax in some versions of IE (most likely IE8 or lower) while variable syntax did work as expected.

Given that functions should not be declated in global namespace, most of functions are local, and therefore it makes sense to use variable syntax for functions always.

Marat Tanalin
  • 12,887
  • 1
  • 32
  • 50
0

I see some different opinions here, but most of them are more based on what you think is better or not, but i don't see the technical reasons on when to use one or another, but for sure there are technical restrictions or advantages in use one declaration formula or another. I'm really a beginner with javascript and I don't feel confident to advise on it, but I will propose a case in which storing a function in a variable is not functional.

In the code below, defining an Angular filter, if I define the function inside a variable, then I can't successfully call it from the filter method. Could anyone explain me the technical reason on this?

See the code (commented is not working):

angular
    .module('loc8rApp')
    .filter('formatDistance', formatDistance);

function formatDistance(){
        return function (distance) {
        var numDistance, unit;
        if (distance && _isNumeric(distance)) {
         if (distance > 1) {
            numDistance = parseFloat(distance).toFixed(1);
            unit = 'km';
          } else {
            numDistance = parseInt(distance * 1000,10);
            unit = 'm';
          }
          return numDistance + unit;
        } else {
          return "?";
        }
      };
};

var _isNumeric = function (n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
};

/*
var formatDistance = function () {
  return function (distance) {
    var numDistance, unit;
    if (distance && _isNumeric(distance)) {
      if (distance > 1) {
        numDistance = parseFloat(distance).toFixed(1);
        unit = 'km';
      } else {
        numDistance = parseInt(distance * 1000,10);
        unit = 'm';
      }
      return numDistance + unit;
    } else {
      return "?";
    }
  };
};
*/

Thank you in advance!

AtomicNation
  • 161
  • 2
  • 5