- The syntax
- Function Declaration
- Function Expression
- Function is a value
- Running at place
- Named function expressions
- Function naming
- Summary
A function, like a variable, can be defined anywhere in the code.
JavaScript provides several ways of defining them:
- Function Declaration
- Function Expression
- Function as a result of a
new Function
call
The syntax
The basic syntax to create a function is a Function Declaration. The syntax is:
function f(arg1, arg2, ...) { ... code ... }
Looks like this:
*!* function sayHi(name) { alert("Hi, "+name) } */!* sayHi('John')
The example above declares a function named
sayHi
with a single argument name
and calls it.
Returning a value
To return a value, use return
statement:
function sum(a, b) { *!*return a+b*/!* } var result = sum(2,5) alert(result)
If a function does not return anything, it’s result is considered to be a special value, undefined
. You can check it out on the following example.
function getNothing() { // no return } var result = getNothing() alert(result)
An empty return gives same result:
function getNothing() { return } alert( getNothing() === undefined ) // true
Local variables
A function may contain variables, defined by var
. Such variables are called local and are only visible inside the function.
function sum(a, b) { var sum = a + b return sum }
Create a function min(a,b)
which takes two numbers and returns the lesser one.
min(2, 5) == 2 min(3, -1) == -1
The code with if
:
function min(a, b) { if (a < b) { return a } else { return b } }
The solution with ternary operator:
function min(a, b) { return a < b ? a : b // a if condition (a<b) is true, b otherwise }
Write a function pow(x,n)
which returns x
in the n-th
power. Or, in other words, x
is multiplied by itself n
times.
pow(3, 2) = 3*3 = 9 pow(3, 3) = 3*3*3 = 27 pow(1, 100) = 1*1*...*1 = 1
Create a page with prompts for x
and n
, then outputs the result of pow(x,n)
.
The demo: tutorial/intro/pow.html
The solution: tutorial/intro/pow.html
Function Declaration
Here in this section, we are not talking about advanced topics like nested functions. They are covered later in Initialization of functions and variables and the next articles.
Everything in due time, right now we need to get the most important stuff right.
Function Declarations are parsed at pre-execution stage, when the browser prepares to execute the code.
That’s why the function declared this way can be called both after and before the definition.
This works:
function sayHi(name) { alert("Hi, "+name) } sayHi("John")
… But changed order also works:
sayHi("John") function sayHi(name) { alert("Hi, "+name) }
A function can be declared anywhere in the code.
For example, we may want to declare a function differently, depending on the condition:
sayHi() if (1) { function sayHi() { alert(1) } } else { function sayHi() { alert(2) } // <-- }
Try running the example above in different browsers. At the time of writing, Firefox gives error, other browsers output 2.
That’s because the declarations are parsed before the execution. According to the specification (p.10.5), the latter function with same name overwrites the existing one.
When it comes to execution, the declarations are ignored. So the if
statement doesn’t affect anything.
Function Expression
A function in JavaScript is a first-class value, just like a number or string.
Anywhere where you could put a value, you can also put a function, declared “at place” with a function expression syntax: function(arguments) { ... }
.
For example, you can do:
var f = 5
But you can also assign it to a function expression:
var f = function(name) { alert("Hi, " + name + "!"); }
The rule is simple.
When the JavaScript parser sees a function
in the main code flow, it assumes Function Declaration.
When a function
comes as a part of a statement, it is a Function Expression.
Function Expressions are created when the execution flow reaches them. As a consequence, Function Expressions can be used only after they are executed.
var sayHi // sayHi() <-- can't call here, there is no sayHi yet if (1) { sayHi = function() { alert(1) } } else { sayHi = function() { alert(2) } } sayHi()
In the example above, the result is the same in all browsers.
Use declarations, please
In the code of unexperienced developers, functions are often declared by expressions:
... code ... var f = function() { ... } ...
Function Declarations are much more readable and shorter. Use them instead.
... code ... function f() { ... } ...
Besides, functions declared this way can be called before it’s definition.
Use expressions only if you mean it. E.g for conditional function definition.
Function is a value
A function in JavaScript is a regular value. We could even output it:
function f() { alert(1) } alert(f)
The example above outputs the function. Usually as the source code.
Both declarations and expression declare a variable and put the function into it. Only the creation time is different.
Passing a function around
Just like any value, a function can be assigned, passed as a parameter for another function and so on.
And it doesn’t matter how it was defined, for example:
function sayHi(name) { alert("Hi, "+name) } var hi = sayHi // assign a function to another variable hi("dude") // call the function
The function is assigned by reference. That is, a function is kept somewhere in memory and sayHi
is a reference (or you could say pointer) to it. When I assign it to hi
, both variables start to reference the same function.
One function can accept another function as an argument.
function runWithOne(f) { // runs given function with argument 1 f(1) } runWithOne( function(a){ alert(a) } )
Logically, a function is an action. So, passing a function around is transferring an action which can be initiated from another part of the program. This feature is widely used in JavaScript.
In the example above, we create a function without a name, and don’t assign it to any variable. Such functions are called anonymous functions.
Running at place
It is possible to create and run a function created with Function Expression at once, like this:
(function() { var a, b // local variables // ... // and the code })()
Running in place is mostly used when we want to do the job involving local variables. We don’t want our local variables to become global, so wrap the code into a function.
After the execution, the global namespace is still clean. That’s a good practice.
Why function
is in brackets? That’s because JavaScript only allows Function Expressions to be called in-place.
Function Declarations can’t be called like that:
function work() { // ... }() // syntax error
Even if we remove the name, JavaScript would see the function
keyword and try to parse Function Delaration:
function() { // error, function declaration without name. // ... }()
So, the only way is to wrap the function in brackets. Then the interpreter consider it as a part of a statement, hence a Function Expression.
If the function is obviously an expression, then there’s no need in wrapping it, for instance:
var result = function(a,b) { return a+b }(2,2) alert(result) // 4
In the code above, the function is created and called instantly.
That’s just like var result = sum(2,2)
, where sum
is replaced by a function expression.
What will be the result of code execution? Why?
var a = 5 (function() { alert(a) })()
P.S. Think well! Pitfall ahead! Ok, you’ve been warned
The result is error. Try it:
var a = 5 (function() { alert(a) })()
That’s because no semicolon after var a = 5
. JavaScript treats the code as:
var a = 5(function() { alert(a) })()
So, it tries to call 5
as if it were a function, which leads to an error. The working code:
var a = 5; (function() { alert(a) })()
This is probably the most dangerous pitfall of optional semicolons in JavaScript.
There is one more way which uses a direct call to Function
constructor. It takes arguments list and body as strings and creates a function from them:
var sayHi = new Function('name', ' alert("Hi, "+name) '); sayHi("Benedict");
It is used very very rarely, almost never.
Named function expressions
A function expression may have a name:
var f = function sayHi(name) { alert("Hi, "+name) }
The syntax is called named function expression (or NFE) and works as it should in all browsers except IE<9.
In those browsers which support it, the name is visible inside the function only:
var f = function sayHi(name) { alert(sayHi) // outputs function } alert(sayHi) // error: undefined variable 'sayHi'
IE will actually create two function objects in such case: sayHi
and f
:
var f = function g() { } // false in IE, error (g is undefined) in other browsers alert(f=== g)
NFEs exist to allow recursive calls from anonymous functions.
See the following factorial
function wrapped into setTimeout
call:
setTimeout(function factorial(n) { return n == 1 ? n : n*factorial(n-1) }, 100)
What is the result of the code? Why?
( function g() { return 1 } ) alert(g)
The answer is error:
( function g() { return 1 } ) alert(g)
The key to the solution is understanding that (function ... )
is a function expression (see Functions: declarations and expressions), not a function definition.
So, we have a named function expression.
The name of a named function expression is visible only inside it.
All browsers except IE<9 support NFEs, so they will give ‘undefined variable’ error, because name g
is only visible inside the function.
IE<9 doesn’t support NFE, so it will output the function.
Function naming
A function is an action. So it’s name should be a verb, like get
, read
, calculateSum
, etc.
Short function names can be allowed if:
- A function is temporary and used only in nearest code. Same logic as with variables.
- A function is used everywhere in the code. So from the one hand, there is no danger to forget what it does, and from the other hand, you have less writing.
The real-world examples are ‘$’, ‘$$’, ‘$A’, ‘$F’ etc. JavaScript libraries use these names to make frequent calls shorter.
In other cases, the name of a function should be a verb or multiple words starting with a verb.
Summary
Functions in JavaScript are regular values. They can be assigned, passed around and called when needed.
- A function which returns nothing actually returns special value:
undefined
. - Use verbs to name functions. Short names are allowable in two edge cases: a name is used in the nearest code only, or it is extremely widely used.
Function Declaration | Function Expression |
---|---|
function is used in the main code flow |
function is created as a part of an expression. |
Created at pre-execution stage. Can be called both before and after the definition. | Created when the execution reaches it. Can be called only after creation. |
Can be called in-place |
Generally, it is recommended to use Declaration
unless there is a reason for Expression
.