More and more I'm seeing functions being declared like
var foo = function() {
// things
};
Instead of how I had learned, like
function foo() {
// things
}
What's the difference? Better performance? Scope? Should I be using this method?
-
it's worth noting that in javascript, functions are first-class-citizens. This allows you to pass around behavior just like objects. This is very useful for callbacks and delegation, among other things.Chris Bye– Chris Bye2012年08月14日 13:32:41 +00:00Commented Aug 14, 2012 at 13:32
-
Scope. The variable name wrapping "//things" is essentially/hopefully preventing name collisions of the "//things" it's wrapping, with other JavaScript (files) included. Another way to think of it is that you have created a namespace "foo".radarbob– radarbob2012年08月14日 17:49:47 +00:00Commented Aug 14, 2012 at 17:49
4 Answers 4
var foo = function() {}
defines a variable that references an anonymous function.
function foo() {}
defines a named function foo
.
Either can be passed by name as function parameters and either can be instantiated if the intended use is for OOP.
At the end of the day, which one you use is largely dictated by your specific use-case (Javascript is fun like that ;)). If you end up using the former, I would strongly suggest that you name the function:
var foo = function MY_function() {}
. This naming convention helps your debugger callstack not be useless.
-
1Got a goof there on function() MY...Erik Reppen– Erik Reppen2012年08月13日 22:37:00 +00:00Commented Aug 13, 2012 at 22:37
-
1@Demian Brecht, and what about var foo = function foo() {...} approach?shabunc– shabunc2012年08月16日 11:40:44 +00:00Commented Aug 16, 2012 at 11:40
-
@shabunc: What about it? It's listed in the last paragraph of my answer.Demian Brecht– Demian Brecht2012年08月16日 15:10:14 +00:00Commented Aug 16, 2012 at 15:10
-
@Demian Brecht, no, actually in last paragraph variable is called
foo
and function is calledMY_function
shabunc– shabunc2012年08月16日 15:12:02 +00:00Commented Aug 16, 2012 at 15:12 -
@shabunc: The name doesn't matter. What matters is the value in the callstack. As an example, [NAMESPACE]_[fn name] is the convention used by Mozilla. The name itself doesn't matter as long as your convention is consistent throughout your project.Demian Brecht– Demian Brecht2012年08月16日 16:31:01 +00:00Commented Aug 16, 2012 at 16:31
function expression:
//someFunction(); //wouldn't work when uncommented
var someFunction = function(){ alert('yay'); };
The func expression in this case is anonymous but assigned to a var for reference. This is different from a labeled function statement in the following ways:
- it can't be hoisted (called before it's defined)
new someFunction().constructor.name === 'someFunction';//false
instances don't get the var name for constructor.name because a reference to the function is assigned to the var but the var, not the function, is tied to the var name
In a labeled function statement:
//someFunction(); //works when uncommented
function someFunction(){ alert('yay'); }
- hoisting works
new someFunction().constructor.name === 'someFunction'; //true
the name is tied directly to the function.
Generally speaking there's not really any great reason to do expression to var unless you want calls to fail if things get moved around or you're defining/assigning a method in one line. I actually find hoisting useful for organizing objects with internal func and method definitions at the bottom so I can get to the actual behavior of the object and do one-line public method definitions (by just assigning funcs to this.
with the same name) all in one spot for ease of reference. You should always try to use labeled statements for constructors, IMO, so you can identify an object's 'type' via its constructor.
Your first example is an expression while the second example is a statement. Defining functions as expressions allows for more flexibility in where the definition can occur, what you can assign it to, that you can pass it as a parameter, etc...
For example:
SomeThing('abc', function(a,b) {return a*b;});
vs...
function tmp(a,b) {
return a*b;
}
SomeThing('abc', tmp);
More complex examples would become obcenely complicated without the function expression syntax.
Look at https://stackoverflow.com/questions/111102/how-do-javascript-closures-work
The main practical difference is hoisting. For example:
foo(); // alerts 'hello'
function foo() {alert('hello');}
vs
foo(); // throws an error since foo is undefined
var foo = function() {alert('hello');}
Also, this is undefined behavior
function foo(){
if (true) {
function bar(){}
}
bar();
}
while this is ok.
function foo(){
if (true) {
var bar = function(){}
}
bar();
}
-
7There's absolutely nothing wrong with defining a function inside a function in JS. There's not many places you can't define a function in JS.Erik Reppen– Erik Reppen2012年08月13日 23:02:52 +00:00Commented Aug 13, 2012 at 23:02
-
2@ErikReppen You definitely can't use a function declarations within non-function blocks (like within an if statement). I can't seem to find where I read they can't be used within another function.Austin– Austin2012年08月14日 05:59:27 +00:00Commented Aug 14, 2012 at 5:59
-
@Austin There's nothing wrong with a function definition within an
if
statement either!Tim– Tim2012年08月14日 10:09:47 +00:00Commented Aug 14, 2012 at 10:09 -
@Austin: Perhaps you read it at w3schools? ;)Demian Brecht– Demian Brecht2012年08月14日 14:28:44 +00:00Commented Aug 14, 2012 at 14:28
-
2@ErikReppen Function expressions can be used anywhere. Function declarations can't be. See stackoverflow.com/questions/10069204/…Austin– Austin2012年08月14日 17:58:18 +00:00Commented Aug 14, 2012 at 17:58