Reputation: 89240
I've recently started maintaining someone else's JavaScript code. I'm fixing bugs, adding features and also trying to tidy up the code and make it more consistent.
The previous developer used two ways of declaring functions and I can't work out if there is a reason behind it or not.
The two ways are:
var functionOne = function() {
// Some code
};
And,
function functionTwo() {
// Some code
}
What are the reasons for using these two different methods and what are the pros and cons of each? Is there anything that can be done with one method that can't be done with the other?
Upvotes: 7656
Views: 1232685
Reputation: 321854
The difference is that functionOne
is a function expression and so only defined when that line is reached, whereas functionTwo
is a function declaration and is defined as soon as its surrounding function or script is executed (due to hoisting).
For example, a function expression:
// TypeError: functionOne is not a function
functionOne();
var functionOne = function() {
console.log("Hello!");
};
And, a function declaration:
// Outputs: "Hello!"
functionTwo();
function functionTwo() {
console.log("Hello!");
}
Historically, function declarations defined within blocks were handled inconsistently between browsers. Strict mode (introduced in ES5) resolved this by scoping function declarations to their enclosing block.
'use strict';
{ // note this block!
function functionThree() {
console.log("Hello!");
}
}
functionThree(); // ReferenceError
Upvotes: 5611
Reputation: 407
There are some differences between arrow function and normal function. In case of an arrow function, you are going to store a function inside a variable. I'm assuming that you have got your concepts clear for hoisting and execution context of JS. If not, please go through this tutorial . Now, let me explain the execution context a bit.
The total execution of your code happens in two phases-
In case of memory allocation, you just need to assign the memory spaces. Like if you do have var x = 4
in your code, after completing phase 1 your program will know, x = undefined
. So, it allocates a memory space for x
but no values in it. Just like a house with no people.
Now, when the code execution phase starts, it will assign the value 4
in x
. Same will happen if you store an arrow function in x
instead of 4
. So that, you can get undefined
if you try to call the arrow function on top of your program.
Now for the conventional function declaration, it will take place in phase one (Memory allocation) of the execution context. So, when the phase two starts, your program already knows what the function is and therefore you can console your function even before declaring it.
Hope it helps.
Upvotes: 0
Reputation: 2448
During a breakpoint in the debugger/DevTools, if you use the format function functionName() {}
in the console, you can't use functionName()
in the console subsequently (it says "not defined"), whereas after var functionName = function() {}
, you can use the function.
See this question.
More generally, the chosen notation might affect hoisting behavior (i.e. from where the function can be called, depending on where it is defined).
Upvotes: 1
Reputation: 48105
Another difference that is not mentioned in the other answers is that if you use the anonymous function and use that as a constructor as in
var functionOne = function() {
// Some code
};
var one = new functionOne();
console.log(one.constructor.name);
then one.constructor.name
will not be defined. Function.name
is non-standard but is supported by Firefox, Chrome, other Webkit-derived browsers and IE 9+.
With
function functionTwo() {
// Some code
}
two = new functionTwo();
it is possible to retrieve the name of the constructor as a string with two.constructor.name
.
Upvotes: 21
Reputation: 25177
@EugeneLazutkin gives an example where he names an assigned function to be able to use shortcut()
as an internal reference to itself. John Resig gives another example - copying a recursive function assigned to another object in his Learning Advanced Javascript tutorial. While assigning functions to properties isn't strictly the question here, I recommend actively trying the tutorial out - run the code by clicking the button in the upper right corner, and double click the code to edit to your liking.
Examples from the tutorial: recursive calls in yell()
:
Tests fail when the original ninja object is removed. (page 13)
function assert(predicate, message) { if(!predicate) { throw new Error(message); } }
var ninja = {
yell: function(n){
return n > 0 ? ninja.yell(n-1) + "a" : "hiy";
}
};
assert( ninja.yell(4) == "hiyaaaa", "A single object isn't too bad, either." );
var samurai = { yell: ninja.yell };
var ninja = null;
try {
samurai.yell(4);
} catch(e){
assert( false, "Uh, this isn't good! Where'd ninja.yell go?" );
}
If you name the function that will be called recursively, the tests will pass. (page 14)
function assert(predicate, message) { if(!predicate) { throw new Error(message); } }
var ninja = {
yell: function yell(n){
return n > 0 ? yell(n-1) + "a" : "hiy";
}
};
assert( ninja.yell(4) == "hiyaaaa", "Works as we would expect it to!" );
var samurai = { yell: ninja.yell };
var ninja = {};
assert( samurai.yell(4) == "hiyaaaa", "The method correctly calls itself." );
console.log(samurai.yell(4));
Upvotes: 26
Reputation: 1598
The first function syntax is Anonymous Function Expression:
var functionOne = function() {
// do something...
};
While, the second one is Function Declaration:
function functionTwo () {
// do something...
}
The main difference between both is the function name since Anonymous Functions have no name to call. Anonymous functions are quick and easy to declare, and many libraries and tools tend to encourage this idiomatic style of code. However, anonymous functions have some drawbacks:
Readability: anonymous functions omit a name which could cause less readable code.
Debugging: anonymous functions have no name in stack traces, which can make debugging more difficult.
Self-Reference: what if the function needs to refer to itself, for recursion for example.
Providing a name for your function expression quite effectively addresses all these drawbacks, and has no tangible downsides. The best practice is to always name your function expressions:
setTimeout(function timeHandler() { // <-- look, a name here!
console.log("I've waited 1 second");
}, 1000);
(function IIFE(str) { // <-- look, always name IIFEs!
console.log(str); // "Hello!"
})('Hello!');
For functions assigned to a variable, naming the function, in this case, is not very common and may cause confusion, in this case, the arrow function may be a better choice.
Upvotes: 14
Reputation: 5351
The following works because function add()
is scoped to the nearest block:
try {
console.log("Success: ", add(1, 1));
} catch(e) {
console.log("ERROR: " + e);
}
function add(a, b){
return a + b;
}
The following does not work because the variable is called before a function value is assigned to the variable add
.
try {
console.log("Success: ", add(1, 1));
} catch(e) {
console.log("ERROR: " + e);
}
var add=function(a, b){
return a + b;
}
The above code is identical in functionality to the code below. Note that explicitly assigning add = undefined
is superfluous because simply doing var add;
is the exact same as var add=undefined
.
var add = undefined;
try {
console.log("Success: ", add(1, 1));
} catch(e) {
console.log("ERROR: " + e);
}
add = function(a, b){
return a + b;
}
The following does not work because var add=
begins an expression and causes the following function add()
to be an expression instead of a block. Named functions are only visible to themselves and their surrounding block. As function add()
is an expression here, it has no surrounding block, so it is only visible to itself.
try {
console.log("Success: ", add(1, 1));
} catch(e) {
console.log("ERROR: " + e);
}
var add=function add(a, b){
return a + b;
}
The name of a function function thefuncname(){}
is thefuncname when it is declared this way.
function foobar(a, b){}
console.log(foobar.name);
var a = function foobar(){};
console.log(a.name);
Otherwise, if a function is declared as function(){}
, the function.name is the first variable used to store the function.
var a = function(){};
var b = (function(){ return function(){} });
console.log(a.name);
console.log(b.name);
If there are no variables set to the function, then the functions name is the empty string (""
).
console.log((function(){}).name === "");
Lastly, while the variable the function is assigned to initially sets the name, successive variables set to the function do not change the name.
var a = function(){};
var b = a;
var c = b;
console.log(a.name);
console.log(b.name);
console.log(c.name);
In Google's V8 and Firefox's Spidermonkey there might be a few microsecond JIT compilation difference, but ultimately the result is the exact same. To prove this, let's examine the efficiency of JSPerf at micro-benchmarks by comparing the speed of two blank code snippets. The JSPerf tests are found here. And, the jsben.ch tests are found here. As you can see, there is a noticeable difference when there should be none. If you are really a performance freak like me, then it might be more worth your while trying to reduce the number of variables and functions in the scope and especially eliminating polymorphism (such as using the same variable to store two different types).
When you use the var
keyword to declare a variable, you can then reassign a different value to the variable like so.
(function(){
"use strict";
var foobar = function(){}; // initial value
try {
foobar = "Hello World!"; // new value
console.log("[no error]");
} catch(error) {
console.log("ERROR: " + error.message);
}
console.log(foobar, window.foobar);
})();
However, when we use the const-statement, the variable reference becomes immutable. This means that we cannot assign a new value to the variable. Please note, however, that this does not make the contents of the variable immutable: if you do const arr = []
, then you can still do arr[10] = "example"
. Only doing something like arr = "new value"
or arr = []
would throw an error as seen below.
(function(){
"use strict";
const foobar = function(){}; // initial value
try {
foobar = "Hello World!"; // new value
console.log("[no error]");
} catch(error) {
console.log("ERROR: " + error.message);
}
console.log(foobar, window.foobar);
})();
Interestingly, if we declare the variable as function funcName(){}
, then the immutability of the variable is the same as declaring it with var
.
(function(){
"use strict";
function foobar(){}; // initial value
try {
foobar = "Hello World!"; // new value
console.log("[no error]");
} catch(error) {
console.log("ERROR: " + error.message);
}
console.log(foobar, window.foobar);
})();
The "nearest block" is the nearest "function," (including asynchronous functions, generator functions, and asynchronous generator functions). However, interestingly, a function functionName() {}
behaves like a var functionName = function() {}
when in a non-closure block to items outside said closure. Observe.
var add=function(){}
try {
// typeof will simply return "undefined" if the variable does not exist
if (typeof add !== "undefined") {
add(1, 1); // just to prove it
console.log("Not a block");
}else if(add===undefined){ // this throws an exception if add doesn't exist
console.log('Behaves like var add=function(a,b){return a+b}');
}
} catch(e) {
console.log("Is a block");
}
var add=function(a, b){return a + b}
function add(){}
try {
// typeof will simply return "undefined" if the variable does not exist
if (typeof add !== "undefined") {
add(1, 1); // just to prove it
console.log("Not a block");
}else if(add===undefined){ // this throws an exception if add doesn't exist
console.log('Behaves like var add=function(a,b){return a+b}')
}
} catch(e) {
console.log("Is a block");
}
function add(a, b){
return a + b;
}
try {
// typeof will simply return "undefined" if the variable does not exist
if (typeof add !== "undefined") {
add(1, 1); // just to prove it
console.log("Not a block");
}else if(add===undefined){ // this throws an exception if add doesn't exist
console.log('Behaves like var add=function(a,b){return a+b}')
}
} catch(e) {
console.log("Is a block");
}
(function () {
function add(a, b){
return a + b;
}
})();
if
, else
, for
, while
, try
/catch
/finally
, switch
, do
/while
, with
)try {
// typeof will simply return "undefined" if the variable does not exist
if (typeof add !== "undefined") {
add(1, 1); // just to prove it
console.log("Not a block");
}else if(add===undefined){ // this throws an exception if add doesn't exist
console.log('Behaves like var add=function(a,b){return a+b}')
}
} catch(e) {
console.log("Is a block");
}
{
function add(a, b){
return a + b;
}
}
var add=function()
try {
// typeof will simply return "undefined" if the variable does not exist
if (typeof add !== "undefined") {
add(1, 1); // just to prove it
console.log("Not a block");
}else if(add===undefined){ // this throws an exception if add doesn't exist
console.log('Behaves like var add=function(a,b){return a+b}')
}
} catch(e) {
console.log("Is a block");
}
(() => {
var add=function(a, b){
return a + b;
}
})();
function add()
try {
// typeof will simply return "undefined" if the variable does not exist
if (typeof add !== "undefined") {
add(1, 1); // just to prove it
console.log("Not a block");
}else if(add===undefined){ // this throws an exception if add doesn't exist
console.log('Behaves like var add=function(a,b){return a+b}')
}
} catch(e) {
console.log("Is a block");
}
(() => {
function add(a, b){
return a + b;
}
})();
Upvotes: 53
Reputation: 127
try {
console.log("Success: ", add(1, 1));
} catch(e) {
console.log("ERROR: " + e);
}
var add=function(a, b){
return a + b;
}
Upvotes: 0
Reputation: 480
In computer science terms, we talk about anonymous functions and named functions. I think the most important difference is that an anonymous function is not bound to a name, hence the name anonymous function. In JavaScript it is a first class object dynamically declared at runtime.
For more information on anonymous functions and lambda calculus, Wikipedia is a good start: Anonymous Functions.
Upvotes: 33
Reputation: 2844
You can't use the .bind()
method on function declarations, but you can on function expressions.
Function declaration:
function x() {
console.log(this)
}.bind('string')
x()
Function expression:
var x = function() {
console.log(this)
}.bind('string')
x()
Upvotes: 1
Reputation: 715
The var functionOne = function() {}
defines at run-time and the function functionTwo() {}
defines at parse-time.
// Run-Time function declaration
functionOne(); // Calling functionOne function here will give an Error
var functionOne = function () {
// Some code
};
// Parse-Time function declaration
functionTwo(); // Calling functionTwo function will not give an Error
function functionTwo() {
// Some code...
}
The explanation between Run-time vs Parse-time javascript run-time vs parse-time
Upvotes: 0
Reputation: 36660
Javascript has first class functions. This means that they can be treated just like any other variable. Functions can be passed as arguments in a function, be returned from a function, and can be stored in variables.
However storing function in a variable (function expression) isn't the only way to create a function, this can also be done via a function declaration. Here are the key differences:
undefined
.Here is an example:
try {
functionOne();
} catch (e) {
console.log('i cant run because im not hoisted');
}
functionTwo();
// function expression, does not get hoisted
let functionOne = function randomName() {
// Some code
};
// function declaration, gets hoisted
function functionTwo() {
console.log('I get hoisted');
}
try {
randomName(); // this isn't the proper name, it is functionOne
} catch (e) {
console.log('You cant call me with randomName my name is function one');
}
:
Upvotes: 3
Reputation: 1329
One important point to note is :-
let there are two functions :-
sum(1,2);
const sum = function(first, second) {
return first + second;
}
In above case, it will give error that sum is not defined, but
sum(1,2);
function sum(first, second) {
return first + second;
}
This function will not any error as Hoisting will take place in this case.
Upvotes: 1
Reputation: 1075735
Here's the rundown on the standard forms that create functions: (Originally written for another question, but adapted after being moved into the canonical question.)
Terms:
The quick list:
Function Declaration
"Anonymous" function
Expression (which despite the term, sometimes create functions with names)
Named function
Expression
Accessor Function Initializer (ES5+)
Arrow Function Expression (ES2015+) (which, like anonymous function expressions, don't involve an explicit name, and yet can create functions with names)
Method Declaration in Object Initializer (ES2015+)
Constructor and Method Declarations in class
(ES2015+)
The first form is a function declaration, which looks like this:
function x() {
console.log('x');
}
A function declaration is a declaration; it's not a statement or expression. As such, you don't follow it with a ;
(although doing so is harmless).
A function declaration is processed when execution enters the context in which it appears, before any step-by-step code is executed. The function it creates is given a proper name (x
in the example above), and that name is put in the scope in which the declaration appears.
Because it's processed before any step-by-step code in the same context, you can do things like this:
x(); // Works even though it's above the declaration
function x() {
console.log('x');
}
Until ES2015, the spec didn't cover what a JavaScript engine should do if you put a function declaration inside a control structure like try
, if
, switch
, while
, etc., like this:
if (someCondition) {
function foo() { // <===== HERE THERE
} // <===== BE DRAGONS
}
And since they're processed before step-by-step code is run, it's tricky to know what to do when they're in a control structure.
Although doing this wasn't specified until ES2015, it was an allowable extension to support function declarations in blocks. Unfortunately (and inevitably), different engines did different things.
As of ES2015, the specification says what to do. In fact, it gives three separate things to do:
The rules for the loose modes are tricky, but in strict mode, function declarations in blocks are easy: They're local to the block (they have block scope, which is also new in ES2015), and they're hoisted to the top of the block. So:
"use strict";
if (someCondition) {
foo(); // Works just fine
function foo() {
}
}
console.log(typeof foo); // "undefined" (`foo` is not in scope here
// because it's not in the same block)
function
ExpressionThe second common form is called an anonymous function expression:
var y = function () {
console.log('y');
};
Like all expressions, it's evaluated when it's reached in the step-by-step execution of the code.
In ES5, the function this creates has no name (it's anonymous). In ES2015, the function is assigned a name if possible by inferring it from context. In the example above, the name would be y
. Something similar is done when the function is the value of a property initializer. (For details on when this happens and the rules, search for SetFunctionName
in the the specification — it appears all over the place.)
function
ExpressionThe third form is a named function expression ("NFE"):
var z = function w() {
console.log('zw')
};
The function this creates has a proper name (w
in this case). Like all expressions, this is evaluated when it's reached in the step-by-step execution of the code. The name of the function is not added to the scope in which the expression appears; the name is in scope within the function itself:
var z = function w() {
console.log(typeof w); // "function"
};
console.log(typeof w); // "undefined"
Note that NFEs have frequently been a source of bugs for JavaScript implementations. IE8 and earlier, for instance, handle NFEs completely incorrectly, creating two different functions at two different times. Early versions of Safari had issues as well. The good news is that current versions of browsers (IE9 and up, current Safari) don't have those issues any more. (But as of this writing, sadly, IE8 remains in widespread use, and so using NFEs with code for the web in general is still problematic.)
Sometimes functions can sneak in largely unnoticed; that's the case with accessor functions. Here's an example:
var obj = {
value: 0,
get f() {
return this.value;
},
set f(v) {
this.value = v;
}
};
console.log(obj.f); // 0
console.log(typeof obj.f); // "number"
Note that when I used the function, I didn't use ()
! That's because it's an accessor function for a property. We get and set the property in the normal way, but behind the scenes, the function is called.
You can also create accessor functions with Object.defineProperty
, Object.defineProperties
, and the lesser-known second argument to Object.create
.
ES2015 brings us the arrow function. Here's one example:
var a = [1, 2, 3];
var b = a.map(n => n * 2);
console.log(b.join(", ")); // 2, 4, 6
See that n => n * 2
thing hiding in the map()
call? That's a function.
A couple of things about arrow functions:
They don't have their own this
. Instead, they close over the this
of the context where they're defined. (They also close over arguments
and, where relevant, super
.) This means that the this
within them is the same as the this
where they're created, and cannot be changed.
As you'll have noticed with the above, you don't use the keyword function
; instead, you use =>
.
The n => n * 2
example above is one form of them. If you have multiple arguments to pass the function, you use parens:
var a = [1, 2, 3];
var b = a.map((n, i) => n * i);
console.log(b.join(", ")); // 0, 2, 6
(Remember that Array#map
passes the entry as the first argument, and the index as the second.)
In both cases, the body of the function is just an expression; the function's return value will automatically be the result of that expression (you don't use an explicit return
).
If you're doing more than just a single expression, use {}
and an explicit return
(if you need to return a value), as normal:
var a = [
{first: "Joe", last: "Bloggs"},
{first: "Albert", last: "Bloggs"},
{first: "Mary", last: "Albright"}
];
a = a.sort((a, b) => {
var rv = a.last.localeCompare(b.last);
if (rv === 0) {
rv = a.first.localeCompare(b.first);
}
return rv;
});
console.log(JSON.stringify(a));
The version without { ... }
is called an arrow function with an expression body or concise body. (Also: A concise arrow function.) The one with { ... }
defining the body is an arrow function with a function body. (Also: A verbose arrow function.)
ES2015 allows a shorter form of declaring a property that references a function called a method definition; it looks like this:
var o = {
foo() {
}
};
the almost-equivalent in ES5 and earlier would be:
var o = {
foo: function foo() {
}
};
the difference (other than verbosity) is that a method can use super
, but a function cannot. So for instance, if you had an object that defined (say) valueOf
using method syntax, it could use super.valueOf()
to get the value Object.prototype.valueOf
would have returned (before presumably doing something else with it), whereas the ES5 version would have to do Object.prototype.valueOf.call(this)
instead.
That also means that the method has a reference to the object it was defined on, so if that object is temporary (for instance, you're passing it into Object.assign
as one of the source objects), method syntax could mean that the object is retained in memory when otherwise it could have been garbage collected (if the JavaScript engine doesn't detect that situation and handle it if none of the methods uses super
).
class
(ES2015+)ES2015 brings us class
syntax, including declared constructors and methods:
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
getFullName() {
return this.firstName + " " + this.lastName;
}
}
There are two function declarations above: One for the constructor, which gets the name Person
, and one for getFullName
, which is a function assigned to Person.prototype
.
Upvotes: 745
Reputation: 341
Another difference between both function is functionOne can be used as a variable that can hold multiple functions within and functionTwo holds some block of code that gets executed all when called. Please check below :
var functionOne = (function() {
return {
sayHello: function(){
console.log('say hello')
},
redirectPage:function(_url){
window.location.href = _url;
}
}
})();
You have a choice which function to be called. e.g functionOne.sayHello or functionOne. redirectPage. And if you call functionTwo then whole block of code will get executed.
Upvotes: 0
Reputation: 5967
This is called a Function Expression:
var getRectArea = function(width, height) {
return width * height;
};
console.log("Area of Rectangle: " + getRectArea(3,4));
// This should return the following result in the console:
// Area of Rectangle: 12
This is called a Function Declaration:
var w = 5;
var h = 6;
function RectArea(width, height) { //declaring the function
return area = width * height;
} //note you do not need ; after }
RectArea(w,h); //calling or executing the function
console.log("Area of Rectangle: " + area);
// This should return the following result in the console:
// Area of Rectangle: 30
Hope this helps explain what is the difference between Function Expression and Function Declaration and how to use them. Thanks.
Upvotes: 6
Reputation: 8673
Expression in JS: Something that returns a value
Example: Try out following in chrome console:
a = 10
output : 10
(1 + 3)
output = 4
Declaration/Statement: Something that does not return a value
Example:
if (1 > 2) {
// do something.
}
here (1>2) is an expression but the 'if' statament is not. Its not returning anything.
Similarly, we have Function Declaration/Statement vs Function Expression
Lets take an example:
// test.js
var a = 10;
// function expression
var fun_expression = function() {
console.log("Running function Expression");
}
// funciton expression
function fun_declaration() {
console.log("Running function Statement");
}
Important: What happens when JavaScript engines runs the above js file.
When this js runs following things will happen:
Now suppose we update the js to.
// test.js
console.log(a) //output: udefined (No error)
console.log(fun_expression) // output: undefined (No error)
console.log(fun_expression()) // output: Error. As we trying to invoke undefined.
console.log(fun_declaration()) // output: running function statement (As fun_declaration is already hoisted in the memory).
var a = 10;
// function expression
var fun_expression = function() {
console.log('Running function expression')
}
// function declaration
function fun_declaration() {
console.log('running function declaration')
}
console.log(a) // output: 10
console.log(fun_expression()) //output: Running function expression
console.log(fun_declaration()) //output: running function declaration
The output mentioned above in the comments, should be useful to understand the different between function expression and function statement/declaration.
Upvotes: 1
Reputation:
I prefer defining function as variable:
let first = function(x){
return x[0];
}
Instead of:
function first(){
....
}
Because i can use expressions and decorators when defining the function. For example:
let safe = function(f){
try {f()...}
}
let last = safe(function(x){return x[0]}).
Also with ES6 its much shorter:
let last = x => x[0]
...........
function last(x){
return x[0];
}
......
let last = safe(x => x[0]);
Upvotes: 3
Reputation: 9588
Hoisting is the JavaScript interpreterโs action of moving all variable and function declarations to the top of the current scope.
However, only the actual declarations are hoisted. by leaving assignments where they are.
Javascript is called loosely typed language. Which means Javascript variables can hold value of any Data-Type. Javascript automatically takes care of changing the variable-type based on the value/literal provided during runtime.
global_Page = 10; var global_Page; ยซ undefined
ยซ Integer literal, Number Type. ------------------- global_Page = 10; ยซ Number
global_Page = 'Yash'; | Interpreted | global_Page = 'Yash'; ยซ String
ยซ String literal, String Type. ยซ AS ยซ global_Page = true; ยซ Boolean
var global_Page = true; | | global_Page = function (){ ยซ function
ยซ Boolean Type ------------------- var local_functionblock; ยซ undefined
global_Page = function (){ local_functionblock = 777;ยซ Number
var local_functionblock = 777; };
// Assigning function as a data.
};
Function
function Identifier_opt ( FormalParameterList_opt ) {
FunctionBody | sequence of statements
ยซ return; Default undefined
ยซ return 'some data';
}
Default return value of function is 'undefined', Variable declaration default value also 'undefined'
Scope with respect to function-block global.
Scope with respect to page undefined | not available.
Function Declaration
function globalAccess() { function globalAccess() {
} ------------------- }
globalAccess(); | | function globalAccess() { ยซ Re-Defined / overridden.
localAccess(); ยซ Hoisted As ยซ function localAccess() {
function globalAccess() { | | }
localAccess(); ------------------- localAccess(); ยซ function accessed with in globalAccess() only.
function localAccess() { }
} globalAccess();
} localAccess(); ยซ ReferenceError as the function is not defined
Function Expression
10; ยซ literal
(10); ยซ Expression (10).toString() -> '10'
var a;
a = 10; ยซ Expression var a.toString() -> '10'
(function invoke() { ยซ Expression Function
console.log('Self Invoking'); (function () {
}); }) () -> 'Self Invoking'
var f;
f = function (){ ยซ Expression var Function
console.log('var Function'); f () -> 'var Function'
};
Function assigned to variable Example:
(function selfExecuting(){
console.log('IIFE - Immediately-Invoked Function Expression');
}());
var anonymous = function (){
console.log('anonymous function Expression');
};
var namedExpression = function for_InternalUSE(fact){
if(fact === 1){
return 1;
}
var localExpression = function(){
console.log('Local to the parent Function Scope');
};
globalExpression = function(){
console.log('creates a new global variable, then assigned this function.');
};
//return; //undefined.
return fact * for_InternalUSE( fact - 1);
};
namedExpression();
globalExpression();
javascript interpreted as
var anonymous;
var namedExpression;
var globalExpression;
anonymous = function (){
console.log('anonymous function Expression');
};
namedExpression = function for_InternalUSE(fact){
var localExpression;
if(fact === 1){
return 1;
}
localExpression = function(){
console.log('Local to the parent Function Scope');
};
globalExpression = function(){
console.log('creates a new global variable, then assigned this function.');
};
return fact * for_InternalUSE( fact - 1); // DEFAULT UNDEFINED.
};
namedExpression(10);
globalExpression();
You can check function declaration, expression test over different browser's using jsperf Test Runner
ES5 Constructor Function Classes: Function objects created using Function.prototype.bind
JavaScript treats functions as first-class objects, so being an object, you can assign properties to a function.
function Shape(id) { // Function Declaration
this.id = id;
};
// Adding a prototyped method to a function.
Shape.prototype.getID = function () {
return this.id;
};
Shape.prototype.setID = function ( id ) {
this.id = id;
};
var expFn = Shape; // Function Expression
var funObj = new Shape( ); // Function Object
funObj.hasOwnProperty('prototype'); // false
funObj.setID( 10 );
console.log( funObj.getID() ); // 10
ES6 introduced Arrow function: An arrow function expression has a shorter syntax, they are best suited for non-method functions, and they cannot be used as constructors.
ArrowFunction : ArrowParameters => ConciseBody
.const fn = (item) => { return item & 1 ? 'Odd' : 'Even'; }; console.log( fn(2) ); // Even console.log( fn(3) ); // Odd
Upvotes: 64
Reputation: 12683
About performance:
New versions of V8
introduced several under-the-hood optimizations and so did SpiderMonkey
.
There is almost no difference now between expression and declaration.
Function expression appears to be faster now.
Anonymous
function expressions appear to have better performance againstNamed
function expression.
Upvotes: 15
Reputation: 104900
They are pretty similar with some small differences, first one is a variable which assigned to an anonymous function (Function Declaration) and second one is the normal way to create a function in JavaScript(Anonymous function Declaration), both has usage, cons and pros:
1. Function Expression
var functionOne = function() {
// Some code
};
A Function Expression defines a function as a part of a larger expression syntax (typically a variable assignment ). Functions defined via Functions Expressions can be named or anonymous. Function Expressions must not start with โfunctionโ (hence the parentheses around the self invoking example below).
Assign a variable to a function, means no Hoisting, as we know functions in JavaScript can Hoist, means they can be called before they get declared, while variables need to be declared before getting access to them, so means in this case we can not access the function before where it's declared, also it could be a way that you write your functions, for the functions which return another function, this kind of declaration could make sense, also in ECMA6 & above you can assign this to an arrow function which can be used to call anonymous functions, also this way of declaring is a better way to create Constructor functions in JavaScript.
2. Function Declaration
function functionTwo() {
// Some code
}
A Function Declaration defines a named function variable without requiring variable assignment. Function Declarations occur as standalone constructs and cannot be nested within non-function blocks. Itโs helpful to think of them as siblings of Variable Declarations. Just as Variable Declarations must start with โvarโ, Function Declarations must begin with โfunctionโ.
This is the normal way of calling a function in JavaScript, this function can be called before you even declare it as in JavaScript all functions get Hoisted, but if you have 'use strict' this won't Hoist as expected, it's a good way to call all normal functions which are not big in lines and neither are a constructor function.
Also, if you need more info about how hoisting works in JavaScript, visit the link below:
https://developer.mozilla.org/en-US/docs/Glossary/Hoisting
Upvotes: 11
Reputation: 2865
An illustration of when to prefer the first method to the second one is when you need to avoid overriding a function's previous definitions.
With
if (condition){
function myfunction(){
// Some code
}
}
, this definition of myfunction
will override any previous definition, since it will be done at parse-time.
While
if (condition){
var myfunction = function (){
// Some code
}
}
does the correct job of defining myfunction
only when condition
is met.
Upvotes: 91
Reputation: 489
In JavaScript there are two ways to create functions:
Function declaration:
function fn(){
console.log("Hello");
}
fn();
This is very basic, self-explanatory, used in many languages and standard across C family of languages. We declared a function defined it and executed it by calling it.
What you should be knowing is that functions are actually objects in JavaScript; internally we have created an object for above function and given it a name called fn or the reference to the object is stored in fn. Functions are objects in JavaScript; an instance of function is actually an object instance.
Function expression:
var fn=function(){
console.log("Hello");
}
fn();
JavaScript has first-class functions, that is, create a function and assign it to a variable just like you create a string or number and assign it to a variable. Here, the fn variable is assigned to a function. The reason for this concept is functions are objects in JavaScript; fn is pointing to the object instance of the above function. We have initialized a function and assigned it to a variable. It's not executing the function and assigning the result.
Reference: JavaScript function declaration syntax: var fn = function() {} vs function fn() {}
Upvotes: 13
Reputation: 21740
A better explanation to Greg's answer
functionTwo();
function functionTwo() {
}
Why no error? We were always taught that expressions are executed from top to bottom(??)
Function declarations and variable declarations are always moved (
hoisted
) invisibly to the top of their containing scope by the JavaScript interpreter. Function parameters and language-defined names are, obviously, already there. ben cherry
This means that code like this:
functionOne(); --------------- var functionOne;
| is actually | functionOne();
var functionOne = function(){ | interpreted |-->
}; | like | functionOne = function(){
--------------- };
Notice that the assignment portion of the declarations were not hoisted. Only the name is hoisted.
But in the case with function declarations, the entire function body will be hoisted as well:
functionTwo(); --------------- function functionTwo() {
| is actually | };
function functionTwo() { | interpreted |-->
} | like | functionTwo();
---------------
Upvotes: 125
Reputation: 5603
An important reason is to add one and only one variable as the "Root" of your namespace...
var MyNamespace = {}
MyNamespace.foo= function() {
}
or
var MyNamespace = {
foo: function() {
},
...
}
There are many techniques for namespacing. It's become more important with the plethora of JavaScript modules available.
Also see How do I declare a namespace in JavaScript?
Upvotes: 72
Reputation: 43956
First I want to correct Greg: function abc(){}
is scoped too — the name abc
is defined in the scope where this definition is encountered. Example:
function xyz(){
function abc(){};
// abc is defined here...
}
// ...but not here
Secondly, it is possible to combine both styles:
var xyz = function abc(){};
xyz
is going to be defined as usual, abc
is undefined in all browsers but Internet Explorer — do not rely on it being defined. But it will be defined inside its body:
var xyz = function abc(){
// xyz is visible here
// abc is visible here
}
// xyz is visible here
// abc is undefined here
If you want to alias functions on all browsers, use this kind of declaration:
function abc(){};
var xyz = abc;
In this case, both xyz
and abc
are aliases of the same object:
console.log(xyz === abc); // prints "true"
One compelling reason to use the combined style is the "name" attribute of function objects (not supported by Internet Explorer). Basically when you define a function like
function abc(){};
console.log(abc.name); // prints "abc"
its name is automatically assigned. But when you define it like
var abc = function(){};
console.log(abc.name); // prints ""
its name is empty — we created an anonymous function and assigned it to some variable.
Another good reason to use the combined style is to use a short internal name to refer to itself, while providing a long non-conflicting name for external users:
// Assume really.long.external.scoped is {}
really.long.external.scoped.name = function shortcut(n){
// Let it call itself recursively:
shortcut(n - 1);
// ...
// Let it pass itself as a callback:
someFunction(shortcut);
// ...
}
In the example above we can do the same with an external name, but it'll be too unwieldy (and slower).
(Another way to refer to itself is to use arguments.callee
, which is still relatively long, and not supported in the strict mode.)
Deep down, JavaScript treats both statements differently. This is a function declaration:
function abc(){}
abc
here is defined everywhere in the current scope:
// We can call it here
abc(); // Works
// Yet, it is defined down there.
function abc(){}
// We can call it again
abc(); // Works
Also, it hoisted through a return
statement:
// We can call it here
abc(); // Works
return;
function abc(){}
This is a function expression:
var xyz = function(){};
xyz
here is defined from the point of assignment:
// We can't call it here
xyz(); // UNDEFINED!!!
// Now it is defined
xyz = function(){}
// We can call it here
xyz(); // works
Function declaration vs. function expression is the real reason why there is a difference demonstrated by Greg.
Fun fact:
var xyz = function abc(){};
console.log(xyz.name); // Prints "abc"
Personally, I prefer the "function expression" declaration because this way I can control the visibility. When I define the function like
var abc = function(){};
I know that I defined the function locally. When I define the function like
abc = function(){};
I know that I defined it globally providing that I didn't define abc
anywhere in the chain of scopes. This style of definition is resilient even when used inside eval()
. While the definition
function abc(){};
depends on the context and may leave you guessing where it is actually defined, especially in the case of eval()
— the answer is: It depends on the browser.
Upvotes: 2102
Reputation: 27486
new Function()
can be used to pass the function's body in a string. And hence this can be used to create dynamic functions. Also passing the script without executing the script.
var func = new Function("x", "y", "return x*y;");
function secondFunction(){
var result;
result = func(10,20);
console.log ( result );
}
secondFunction()
Upvotes: 7
Reputation: 1144
Both are different ways of defining a function. The difference is how the browser interprets and loads them into an execution context.
The first case is of function expressions which loads only when the interpreter reaches that line of code. So if you do it like the following, you will get an error that the functionOne is not a function.
functionOne();
var functionOne = function() {
// Some code
};
The reason is that on the first line no value is assigned to functionOne, and hence it is undefined. We are trying to call it as a function, and hence we are getting an error.
On the second line we are assigning the reference of an anonymous function to functionOne.
The second case is of function declarations that loads before any code is executed. So if you do like the following you won't get any error as the declaration loads before code execution.
functionOne();
function functionOne() {
// Some code
}
Upvotes: 12
Reputation: 929
I'm listing out the differences below:
A function declaration can be placed anywhere in the code. Even if it is invoked before the definition appears in code, it gets executed as function declaration is committed to memory or in a way it is hoisted up, before any other code in the page starts execution.
Take a look at the function below:
function outerFunction() {
function foo() {
return 1;
}
return foo();
function foo() {
return 2;
}
}
alert(outerFunction()); // Displays 2
This is because, during execution, it looks like:-
function foo() { // The first function declaration is moved to top
return 1;
}
function foo() { // The second function declaration is moved to top
return 2;
}
function outerFunction() {
return foo();
}
alert(outerFunction()); //So executing from top to bottom,
//the last foo() returns 2 which gets displayed
A function expression, if not defined before calling it, will result in an error. Also, here the function definition itself is not moved to the top or committed to memory like in the function declarations. But the variable to which we assign the function gets hoisted up and undefined gets assigned to it.
Same function using function expressions:
function outerFunction() {
var foo = function() {
return 1;
}
return foo();
var foo = function() {
return 2;
}
}
alert(outerFunction()); // Displays 1
This is because during execution, it looks like:
function outerFunction() {
var foo = undefined;
var foo = undefined;
foo = function() {
return 1;
};
return foo ();
foo = function() { // This function expression is not reachable
return 2;
};
}
alert(outerFunction()); // Displays 1
It is not safe to write function declarations in non-function blocks like if because they won't be accessible.
if (test) {
function x() { doSomething(); }
}
Named function expression like the one below, may not work in Internet Explorer browsers prior to version 9.
var today = function today() {return new Date()}
Upvotes: 19
Reputation: 13811
Greg's Answer is good enough, but I still would like to add something to it that I learned just now watching Douglas Crockford's videos.
Function expression:
var foo = function foo() {};
Function statement:
function foo() {};
The function statement is just a shorthand for var
statement with a function
value.
So
function foo() {};
expands to
var foo = function foo() {};
Which expands further to:
var foo = undefined;
foo = function foo() {};
And they are both hoisted to the top of the code.
Upvotes: 33