They're actually really similar. How you call them is exactly the same.The difference lies in how the browser loads them into the execution context.
Function declarations load before any code is executed.
Function expressions load only when the interpreter reaches that line of code.
So if you try to call a function expression before it's loaded, you'll get an error! If you call a function declaration instead, it'll always work, because no code can be called until all declarations are loaded.
Example: Function Expression
alert(foo()); // ERROR! foo wasn't loaded yet
var foo = function() { return 5; }
Example: Function Declaration
alert(foo()); // Alerts 5. Declarations are loaded before any code can run.
function foo() { return 5; }
As for the second part of your question:
var foo = function foo() { return 5; } is really the same as the other two. It's just that this line of code used to cause an error in safari, though it no longer does.
They're actually really similar. How you call them is exactly the same.The difference lies in how the browser loads them into the execution context.
Function declarations load before any code is executed.
Function expressions load only when the interpreter reaches that line of code.
So if you try to call a function expression before it's loaded, you'll get an error! If you call a function declaration instead, it'll always work, because no code can be called until all declarations are loaded.
Example: Function Expression
alert(foo()); // ERROR! foo wasn't loaded yet
var foo = function() { return 5; }
Example: Function Declaration
alert(foo()); // Alerts 5. Declarations are loaded before any code can run.
function foo() { return 5; }
As for the second part of your question:
var foo = function foo() { return 5; } is really the same as the other two. It's just that this line of code used to cause an error in safari, though it no longer does.
Function Declaration
function foo() { ... }
Because of function hoisting, the function declared this way can be called both after and before the definition.
Function Expression
Named Function Expression
var foo = function bar() { ... }Anonymous Function Expression
var foo = function() { ... }
foo() can be called only after creation.
Immediately-Invoked Function Expression (IIFE)
(function() { ... }());
Conclusion
Douglas Crockford recommends to use function expression in his «JavaScript: The Good Parts» book because it makes it clear that foo is a variable containing a function value.
Well, personally, I prefer to use Declaration unless there is a reason for Expression.
Along with that very good answer, the only advantage I can see is dynamically changing a function call.
For example this code :
function foo(){
console.log('foo');
}
function bar(){
console.log('bar');
}
var myFn = foo;
myFn();
setInterval(function(){
if(myFn === foo) myFn = bar;
else myFn = foo;
}, 5000);
setInterval(function(){
myFn()
}, 6000);
It will never log the same thing since you reassign a global variable, every innerscope function will change while this code :
function foo(){
console.log('foo');
}
setInterval(function(){
function foo(){
console.log('Changed foo');
}
foo()
}, 5000)
setInterval(function(){
foo()
}, 5000)
Will log 2 different things. You can only change the current scope function, not the global.
My Experiment: function expression we need to use when use that function in different scopes. For example.
function outer(){
function inner(){
}
}
outer();
inner();// Error ...calling inner..will not be found..
-this will not work. But
var inner;
function outer(){
inner=function(){
}
}
outer();
inner();// will work
-this will work
Why is it called a function expression and not a function declaration?
Function expressions vs function declarations: return value
Function Declaration vs Expression
oop - Know JavaScript Function Expression vs Function Declaration, but what is this? Named Function Expression? - Stack Overflow
Videos
Interesting question. Wording can have soft boundaries, which is partly what causes this confusion.
First, some rough definitions:
- Expression: I think this is best thought of with an example.
2 * 2is an expression, because you can continue doing other operations on it, like2 * 2 - 3.if (...)on the other hand is not an expression in javascript, it does not resolve into a value in which you can do further operations on. It's invalid to doif (...) {...} / 2. This "definition" has some holes, but should be good enough for the purposes of this answer. - Declaration: A declaration is just declaring that you're going to use a certain variable name. So, in your example with
const foo = 5, It's theconst foopart that actually declares, the= 5is just initializing the declaration.
With that in mind, lets consider two examples of functions, and see how this terminology plays into these examples:
const g = function() {}
There is a declaration going on here, the const g. We also see that there's a function being created and assigned to g. We're doing something with the result of function() {} (we're assigning it to something), which means javascript will interpret this as a function expression.
function f() {}
We're not using this function as an expression (we're not doing any additional operations with it after we create it), so javascript will actually treat this different from our first example. It's going to declare f in the local namespace, and it's going to apply function hoisting. If you simply added a + before function f() {}, then you would cause javascript to interpret this as an expression instead, and these features will be disabled. You can try it in the dev tools - put in +function f(){} or const g = function f(){}, and f will remain undefined.
The fact that javascript treats the function keyword differently in different contexts is at the heart of this language choice. You can almost think of the "function" keyword as having two different meaning, and the chosen meaning depends on the context. Any time the function is used in an expression context or when it's unnamed, then it takes on the "expression" form, and we call it a "function expression". Otherwise, it takes on the alternative form that contains some extra features, like declaring the function name as a local variable. This is probably why we've adopted to call this alternative form a function declaration. However, like the OP rightly pointed out, even with const f = function() {}, a declaration is still happening, it's just not happening by the function keyword.
Footnote: With examples like +function f() {}, f won't be defined in the same scope as g, but it does get defined inside the body of f. In other words, any named function expression declares its name within its own body.
Then why is this called a function expression?:
Assigning a variable a value, is in fact, an expression. In your example foo = 5, that is an expression. You are also declaring foo, but its still an expression.
Similarly, the other example const bar = function() {} is called a function expression to differentiate between a function declaration, and a function expression.
Function expression
const bar = function() {
// Some code
};
vs Function declaration
function foo() {
// Some code
};
To understand what this really is about, we need to dig into the JavaScript grammar:
In ECMAScript a script consists of Statements and Declarations. A Statement can be (amongst others) an ExpressionStatement. Note that ExpressionStatement is explicitly defined as:
ExpressionStatement[Yield, Await]:
[lookahead ∉ { {,
function,async[no LineTerminator here]function,class,let[ }]Expression[+In, ?Yield, ?Await];
This looks really cumbersome, but what it says is that an ExpressionStatement cannot possibly start with the keyword function. So if you just write:
function a() {}
This can never be interpreted as an expression although in other circumstances like
const a = function a() {}
it is an expression. (The right hand side of an assignment operation always must be an expression.)
Now, only expressions evaluate a value, statements do not. This is all the text you quote is saying in a hard to understand way.
A function declaration defines a function and does not require a variable to be assigned to it:
True but redundant. A declaration cannot occur at the right hand-side of an assignment.
It simply declares a function, and doesn't itself return a value ...
Yeah, statements do not evaluate to ("return") a value.
On the other hand, a function expression does return a value.
Sure, like any expression.
See https://www.ecma-international.org/ecma-262/8.0/#prod-StatementList
On the other hand, a function expression does return a value.
This is confusing
Yes indeed. What they actually meant was a function expression evaluates to a (function) value - in contrast to a declaration, which is not an expression but a statement and doesn't evaluate to anything. It has nothing do with the value that the function might return from a call.
So I understand the difference between the two, but is it a case where I should've use a certain one instead of the other ? Or could I just use function expression for everything?
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".
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.
Firefox also has non-standard Function Statements, which makes it possible to conditionally choose between function declarations (per spec, you can't). Just using an example of Juriy "kangax" Zaytsev:
if (true) {
function foo(){ return 1; }
} else {
function foo(){ return 2; }
}
foo(); // 1
// Note that other clients interpet `foo` as function declaration here,
// overwriting first `foo` with the second one, and producing "2", not "1" as a result
So those are compiled at execution time, instead of in the parse-phase:
Function statements are NOT declared during variable instantiation. They are declared at run time, just like function expressions.
Other browsers probably will pre-compile function declarations, making them perform faster at run time, but Firefox has to interpret function declarations at run time, causing not much difference between the speed of function declarations and function expressions in Gecko-based browsers.
This has to be a browser dependent issue. Some browsers may compile the javascript differently if it's an expression rather than a declaration and some might treat them exactly the same.
You can call the function assigned to a variable, but you have to assign it before you can call it:
function myClass() {
var myFunc1 = function() {
}
myFunc1() //success
myFunc2() //success
function myFunc2() {
}
}
Those functions are local to the constructor, so it's not the same as using the prototype. To make a public function you need to assign it to the object:
function myClass() {
this.myPublicFunc1 = function() {
}
this.myPublicFunc2 = myFunc2;
function myFunc2() {
}
}
var o = new myClass();
o.myPublicFunc1() //success
o.myPublicFunc2() //success
You must use an expression if you want to invoke the function immediately.
This one invokes it and assigns the return value to the variable:
function myClass {
var myVar = function() {
return 'some value'; // <--- 2. assign the return value to the variable
}(); // <--- 1. invoke the function immediately
function myFunc2() {
}
}
This one invokes it, but assigns the function itself to the variable:
function myClass {
var myFunc1;
(myFunc1 = function() { // <--- 1. assign the function to the variable
// Do something
})(); // <--- 2. invoke the function immediately
function myFunc2() {
}
}
Both are equivalent in terms of scope. A function declared inside another function will not be global. The difference is that you can use a declared function at any time (because it's hoisted before any code is run), a function assigned to a variable as an expression only after you have assigned it.
(function () {
bar(); // works
function bar() { } // is not global
foo(); // doesn't work
var foo = function () { };
})();
As far as polluting the enclosing scope goes, both are equivalent. Note that it is not necessarily the global scope - it is the scope in which the function is declared (local functions are permitted within other functions). In your example, both methods introduce a variable (function object) named sum into the local scope.