Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Video may be blocked due to browser extensions. In the article you will find a solution to this problem.

It is very easy to make mistakes when you have to handle variables, change them, keep track, etc. Especially in a loop. A great way to understand what's going on is to use the simplest debugging technique — `console.log`

. Recall, this function prints onto the screen whatever you pass to it.

For example, I'm trying to understand what's happening inside a while loop:

```
while (counter <= n) {
result = result * result;
counter = counter + 1;
}
```

I'm going to add console.log here:

```
while (counter <= n) {
result = result * result;
counter = counter + 1;
console.log(result)
}
```

Now, each time this block of code repeats, the `result`

variable will be printed. Let's see:

```
1
1
1
```

*(I'm running the function with n equals 3)*

The `result`

in each step is 1. This is not right, the `result`

should increase each step... Okay, so, the problem is probably in the line where `result`

is changing. Right! I have `result = result * result`

, but I need to multiply `result`

by `counter`

, not by `result`

.

```
1
2
6
```

Now it works! I see the steps now, and the last step produces the correct answer: 3! is 6.

Don't hesitate to put `console.log`

wherever. It's your best friend :-)

Since a while loop simply checks the condition, we can create infinite loops if we make the condition to be always true.

```
while (10 > 5) {
console.log("Ten is still larger than 5");
}
```

This will print "Ten is still larger than 5" until the heat death of the universe, or until you close the program, or until your computer runs out of memory, whatever comes first. Because the condition `10 > 5`

is always true.

An even simpler way to make an infinite loop is `while (true) { ... }`

. `true`

is always true.

Sometimes your loops will be infinite, even if you didn't plan on that. This is a common problem, and it only means that inside the loop you have forgotten to change the thing that is being checked. For example, if I delete the line `counter = counter + 1`

from today's lesson's loop:

```
while (counter <= n) {
result = result * result;
}
```

... I'll end up with an infinite loop: counter never changes, so if `counter <= n`

, it is true forever.

**Variables** are like constants, but you can change their values at any moment.

```
let age = 21;
age = 22; // now age is 22
age = age + 10; // now age is 32
```

**Loops** are repeated blocks of code. A **while loop** is a block repeated while some *condition* is true.

```
while (condition) {
do_stuff;
}
```

Here is the factorial function with a while loop:

```
const factorial = (n) => {
let counter = 1;
let result = 1;
while (counter <= n) {
result = result * counter;
counter = counter + 1;
}
return result;
}
```

Idea: make `counter`

= 1, then multiply `result`

by `counter`

repeatedly, while counting up to `n`

(the number passed to the function). When `counter`

becomes larger than `n`

— stop. By then, `result`

will be the answer.

This is **iteration** — defined repetition of code. Different languages have different ways to to iteration. A while loop is one of the ways JavaScript offers.

Compare a recursive factorial (from lesson 8) and a non-recursive factorial (from today):

```
const recursiveFactorial = (n) => {
if (n === 1) {
return 1;
}
return n * recursiveFactorial(n-1);
}
const factorial = (n) => {
let counter = 1;
let result = 1;
while (counter <= n) {
result = result * counter;
counter = counter + 1;
}
return result;
}
```

This recursive function is **declarative** — it's like a definition of factorial. It declares what factorial is.

This non-recursive iterative function is **imperative** — it's a description of what to do in order to find factorial.

Declarative comes from Latin "clarare" — *to make clear, to announce, to make a declaration*. You declare — I want factorial of n to be n times factorial of n-1.

Imperative comes from latin "imperare", it means *"to command"*. You command the steps precisely — multiply this and that while counting down and keep some numbers in mind.

Declarative is what. Imperative is how.

Writing declarative code is, in general, a better idea. Your code will be easier to read and understand, and it will be easier to build upon. But sometimes you have no choice.

Many bugs come from the changing state*, and **assignment statements** that perform changes are often the root cause of all the evil in the universe.

So, when it comes to the assignment statement, **tread lightly**.

We are already familiar with a way of naming things using constants. For example, here is a constant `pi`

with a value of `3.14`

.

```
const pi = 3.14;
```

After this line, every time we see `pi`

we know it means `3.14`

. It's called a constant because, well, it's constant, permanent. After this line `pi`

is always `3.14`

, it won't ever change. This is why in the paper analogy I was using a pen after all.

This might seem restrictive, but this is actually rather good. Changing the things we create is difficult to deal with. Imagine writing code using some constant and not being sure it's what you think it is.

Nevertheless, sometimes you need to be able to change things you create or change their values, in other words. Say, you want to do something 5 times. One way is to do it repeatedly while counting to 5, and then stop. For this, you'd need something to store this counter, this changing number. A constant won't work — it's permanent, you can't change its value after creating.

This is why JavaScript and most other programming languages have a concept of a "variable". Think of a variable as a piece of paper with a name written with a pen, but a value written with a pencil. At any moment you can replace the value with a different one.

We can calculate a factorial with a variable like so:

```
let factorial = 1;
factorial = factorial * 2; // 2
factorial = factorial * 3; // 6
factorial = factorial * 4; // 24
factorial = factorial * 5; // 120
```

Creating a variable is easy, it looks like a constant, but instead of `const`

we say `let`

. We let it be a thing, and this is not forever.

Next, we change the value of `factorial`

. We couldn't have done this if `factorial`

was a constant. This line means "make the factorial be whatever factorial times 2 is". So JavaScript multiplies factorial by 2 and stores this result in the `factorial`

variable. Before `factorial`

was 1, and now it is 2.

We repeat this 3 more times, every time multiplying the number by the next integer: by 3, by 4 and by 5. This is what you might do in your head when multiplying numbers. You probably don't think about it explicitly, but this would be a way of explaining the process of computation if you were to explain it.

This idea of using a counter to repeat something multiple times is common in programming, and most programming languages have "loops" for this. Let's look at one particular type of a loop — a "while loop". It's a block of code that is repeated while some condition is met.

Think of a farmer who works from sunrise till sunset. In other words, he works while the sun is up. You could say:

```
while (sun is up) {
work
}
```

This is not valid JavaScript, of course, this is just to give you an idea. This "work" thing is going to be repeated again and again, while the sun is up. This means after each repetition we need to check if the sun is still up, and stop if it isn't. In other words: check, do if it's true, check, do if it's true, check... etc.

Okay, so here is the factorial function with variables and a loop instead of recursion.

```
const factorial = (n) => {
let counter = 1;
let result = 1;
while (counter <= n) {
result = result * counter;
counter = counter + 1;
}
return result;
}
```

Woah, what's going on here? First, we create two variables: one for the counter, to count from 1 to the upper limit, and the second — for the running result.

Then the main part begins — a while loop that repeats while the counter is less than or equal to n — the number passed to this function. The code that is repeated is simple: we change the values of our two variables. Running result is multiplied by the counter, and the counter itself is incremented by 1.

At some point this condition — "counter is less than or equal to n" — will become false, so the loop will no longer be repeating and the program will continue to the next thing — `return result`

. By then, the result will be the answer, because, during those repetitions in the loop, the result was being multiplied by 1, then by 2, then 3, etc, until n, whatever that is.

Let's see what the computer does step by step when we call factorial of 3.

- Take one argument — number 3, known as
`n`

inside - Create a variable
`counter`

, set its value to 1 - Create a variable
`result`

, set its value to 1 - Check: counter is 1, it's less than or equal to
`n`

, so - Multiply
`result`

by`counter`

and put the answer — 1 — into`result`

- Add 1 to
`counter`

and put the answer — 2 — into`counter`

- Go back and check:
`counter`

is 2, it's less than or equal to`n`

, so - Multiply
`result`

by`counter`

and put the answer — 2 — into`result`

- Add 1 to
`counter`

and put the answer — 3 — into`counter`

- Go back and check:
`counter`

is 3, it's less than or equal to`n`

, so - Multiply
`result`

by`counter`

and put the answer — 6 — into`result`

- Add 1 to
`counter`

and put the answer — 4 — into`counter`

- Go back and check:
`counter`

is 4, it's not less than or equal to`n`

, so don't repeat anymore and continue to the next line in the program - Return
`result`

— 6

Computer does this billion times faster but does the same thing. This kind of defined repetition is called an "iteration" in general. Our program uses iteration to calculate a factorial.

Last time we've seen an iterative process with recursion, and this time — an iteraritve process without recursion.

Both use the technique of iteration, but with recursive calls, we didn't have to change the values, we just passed the new values to the next function call. On the other hand, this factorial function doesn't have any recursive function calls, so all the transformations should happen inside a single instance, a single function box. We have no other choice but to change the values of things.

This is the first time in our course when we actually change the values of things. We haven't done this before but we were still able to compute.

The style of programming you've seen before this lesson is called "declarative". The style of programming you've seen today, with changing values, is called "imperative".

Compare a recursive factorial and a non-recursive factorial:

```
const recursiveFactorial = (n) => {
if (n === 1) {
return 1;
}
return n * recursiveFactorial(n-1);
}
const factorial = (n) => {
let counter = 1;
let result = 1;
while (counter <= n) {
result = result * counter;
counter = counter + 1;
}
return result;
}
```

This recursive function is declarative — it's like a definition of factorial. It declares what factorial is.

This non-recursive iterative function is imperative — it's a description of what to do in order to find factorial.

Declarative comes from Latin "clarare" — to make clear, to announce, to make a declaration. You declare — I want factorial of n to be n times factorial of n-1.

Imperative comes from latin "imperare", it means "to command". You command the steps precisely — multiply this and that while counting down and keep some numbers in mind.

Declarative is what. Imperative is how.

Writing declarative code is, in general, a better idea. Your code will be easier to read and understand, and it will be easier to build upon. Some languages tend to push you towards one side or the other, and some even leave you no choice, but ultimately you have to learn to see when imperative approach gives you more problems than solutions. Keeping track of changing variables is hard, and even a handful of variables make the system too complex to think about. Many bugs come from the changing state, and assignment statements that perform changes are often the root cause of all the evil in the universe.

Music: http://www.bensound.com

The Hexlet support team or other students will answer you.

Ошибки, сложный материал, вопросы >
###### Нашли опечатку или неточность?

###### Что-то не получается или материал кажется сложным?

###### Об обучении на Хекслете

Выделите текст, нажмите
`ctrl + enter`
и отправьте его нам. В течение нескольких дней мы исправим ошибку или улучшим формулировку.

Загляните в раздел «Обсуждение»:

- задайте вопрос. Вы быстрее справитесь с трудностями и прокачаете навык постановки правильных вопросов, что пригодится и в учёбе, и в работе программистом;
- расскажите о своих впечатлениях. Если курс слишком сложный, подробный отзыв поможет нам сделать его лучше;
- изучите вопросы других учеников и ответы на них. Это база знаний, которой можно и нужно пользоваться.

- Статья «Как учиться и справляться с негативными мыслями»
- Статья «Ловушки обучения»
- Статья «Сложные простые задачи по программированию»
- Урок «Как эффективно учиться на Хекслете»
- Вебинар «Как самостоятельно учиться»

Programming courses for beginners and experienced developers. Start training for free.

- 120 courses, 2000+ hours of theory
- 900 practical tasks in a browser
- 360 000 students

Our graduates work in companies:

Sign up or sign in