◐ Shell
reader mode source ↗
Skip to content
Merged
Changes from all commits
File filter
Conversations
Jump to
Diff view
Apply and reload
Show whitespace
Diff view
Apply and reload
115 changes: 58 additions & 57 deletions 1-js/02-first-steps/15-function-basics/article.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,40 @@
# Functions

Quite often we need to perform a similar action in many places of the script.

For example, we need to show a nice-looking message when a visitor logs in, logs out and maybe somewhere else.

Functions are the main "building blocks" of the program. They allow the code to be called many times without repetition.

We've already seen examples of built-in functions, like `alert(message)`, `prompt(message, default)` and `confirm(question)`. But we can create functions of our own as well.

## Function Declaration

To create a function we can use a *function declaration*.

It looks like this:

```js
function showMessage() {
alert( 'Hello everyone!' );
}
```

The `function` keyword goes first, then goes the *name of the function*, then a list of *parameters* between the parentheses (comma-separated, empty in the example above, we'll see examples later) and finally the code of the function, also named "the function body", between curly braces.

```js
function name(parameter1, parameter2, ... parameterN) {
...body...
}
```

Our new function can be called by its name: `showMessage()`.

For instance:

```js run
function showMessage() {
alert( 'Hello everyone!' );
}

*!*
Expand All @@ -43,96 +43,96 @@ showMessage();
*/!*
```

The call `showMessage()` executes the code of the function. Here we will see the message two times.

This example clearly demonstrates one of the main purposes of functions: to avoid code duplication.

If we ever need to change the message or the way it is shown, it's enough to modify the code in one place: the function which outputs it.

## Local variables

A variable declared inside a function is only visible inside that function.

For example:

```js run
function showMessage() {
*!*
let message = "Hello, I'm JavaScript!"; // local variable
*/!*

alert( message );
}

showMessage(); // Hello, I'm JavaScript!

alert( message ); // <-- Error! The variable is local to the function
```

## Outer variables

A function can access an outer variable as well, for example:

```js run no-beautify
let *!*userName*/!* = 'John';

function showMessage() {
let message = 'Hello, ' + *!*userName*/!*;
alert(message);
}

showMessage(); // Hello, John
```

The function has full access to the outer variable. It can modify it as well.

For instance:

```js run
let *!*userName*/!* = 'John';

function showMessage() {
*!*userName*/!* = "Bob"; // (1) changed the outer variable

let message = 'Hello, ' + *!*userName*/!*;
alert(message);
}

alert( userName ); // *!*John*/!* before the function call

showMessage();

alert( userName ); // *!*Bob*/!*, the value was modified by the function
```

The outer variable is only used if there's no local one.

If a same-named variable is declared inside the function then it *shadows* the outer one. For instance, in the code below the function uses the local `userName`. The outer one is ignored:

```js run
let userName = 'John';

function showMessage() {
*!*
let userName = "Bob"; // declare a local variable
*/!*

let message = 'Hello, ' + userName; // *!*Bob*/!*
alert(message);
}

// the function will create and use its own userName
showMessage();

alert( userName ); // *!*John*/!*, unchanged, the function did not access the outer variable
```

```smart header="Global variables"
Variables declared outside of any function, such as the outer `userName` in the code above, are called *global*.

Global variables are visible from any function (unless shadowed by locals).

It's a good practice to minimize the use of global variables. Modern code has few or no globals. Most variables reside in their functions. Sometimes though, they can be useful to store project-level data.
```

## Parameters
Expand Down Expand Up @@ -191,7 +191,7 @@ If a function is called, but an argument is not provided, then the corresponding
For instance, the aforementioned function `showMessage(from, text)` can be called with a single argument:

```js
showMessage("Ann");
```

That's not an error. Such a call would output `"*Ann*: undefined"`. As the value for `text` isn't passed, it becomes `undefined`.
Expand Down @@ -330,13 +330,14 @@ function showMovie(age) {

In the code above, if `checkAge(age)` returns `false`, then `showMovie` won't proceed to the `alert`.

````smart header="A function with an empty `return` or without it returns `undefined`"
If a function does not return a value, it is the same as if it returns `undefined`:

```js run
function doNothing() { /* empty */ }

alert( doNothing() === undefined ); // true
```

An empty `return` is also the same as `return undefined`:
Expand All @@ -346,9 +347,10 @@ function doNothing() {
return;
}

alert( doNothing() === undefined ); // true
```
````

````warn header="Never add a newline between `return` and the value"
For a long expression in `return`, it might be tempting to put it on a separate line, like this:
Expand Down Expand Up @@ -376,7 +378,7 @@ return (
)
```
And it will work just as we expect it to.
````

## Naming a function [#function-naming]

Expand Down Expand Up @@ -440,12 +442,11 @@ The first variant uses a label:
```js
function showPrimes(n) {
nextPrime: for (let i = 2; i < n; i++) {

for (let j = 2; j < i; j++) {
if (i % j == 0) continue nextPrime;
}

alert( i ); // a prime
}
}
```
Expand All @@ -470,7 +471,7 @@ function isPrime(n) {
}
```

The second variant is easier to understand, isn't it? Instead of the code piece we see a name of the action (`isPrime`). Sometimes people refer to such code as *self-describing*.

So, functions can be created even if we don't intend to reuse them. They structure the code and make it readable.

Expand Down
Toggle all file notes Toggle all file annotations