diff --git a/1-js/2-first-steps/17-let-var-const/article.md b/1-js/2-first-steps/17-let-var-const/article.md index 3bcf3bf8..2c99e104 100644 --- a/1-js/2-first-steps/17-let-var-const/article.md +++ b/1-js/2-first-steps/17-let-var-const/article.md @@ -1,5 +1,109 @@ # Let, const and var revisited -Now as we know most language syntax constructs, let's recall `let`, `var` and `const` and make sure we understand the difference. +Now as we know most language syntax constructs, let's discuss the subtle features and differences between variable definitions: `let`, `var` and `const`. + +## Let + +We'll start with `let`, because in the modern code this declaration appears far more often than any other. + +### Let is local to the block + +A variable declared with `let` is local to the containing `{…}`. + +In other words, the variable is only visible inside the block `{…}` where it was declared. + +For instance, let's consider the following code: + +```js +//+ run +'use strict'; + +let user = "John"; + +alert(`Hello ${user}!`); // Hello John! + +if (true) { +*!* + let user = "Pete"; +*/!* + alert(`…working with ${user}`); // …working with Pete +} + +alert(`Goodbye ${user}!`); // Goodbye John! +``` + +Here the if-block declares and uses it's own variable named `"user"`. The code inside that `if` will see and use the local variable ("Pete"). And after the `if` finished, the if-local `user` is no longer seen ("John" again). + +Let's see what happens if we remove the `let` inside `if`: + +```js +//+ run +'use strict'; + +let user = "John"; + +alert(`Hello ${user}!`); // Hello John! + +if (true) { +*!* + user = "Pete"; +*/!* + alert(`…working with ${user}`); // …working with Pete +} + +alert(`Goodbye ${user}!`); // Goodbye *!*Pete*/!*! +``` + +Now there is no declaration inside `if`, there's no local `user`, hence the outer (the only declared) variable is used and modified. + +The same applies to other `{…}` blocks, including `for`, `while`, `switch` and other constructs. + +[smart header="`let` in `for` is also local"] +In `for(let i=…)` the variable declared inside `for` is local to the loop body. + +For instance, `i` in the example below is visible only inside the loop: + +```js +//+ run +'use strict'; + +for(let i = 0; i < 3; i++) { + // ...i becomes: 0, 1, 2 + alert(i); +} + +// i no longer exists here +alert(i); // Error: i is not defined! +``` +[/smart] + +### Let is visible only after the declaration + +The variable can only be used after it is declared: + +```js +//+ run +'use strict'; + +alert(message); // Error, the variable does not exist yet! + +let message = "hello"; +``` + +In the code above we must put `alert` after `let message` for it to work. + +That seems to be obvious. But a little later we'll see that `var` behaves differently here. + +## Const + +A variable declared with `const` is exactly the same as `let` except that it cannot be modified. + +The visibility rules are same. + +## Var + + + + diff --git a/1-js/2-first-steps/18-function-basics/article.md b/1-js/2-first-steps/18-function-basics/article.md index 44e56919..226d7386 100644 --- a/1-js/2-first-steps/18-function-basics/article.md +++ b/1-js/2-first-steps/18-function-basics/article.md @@ -48,9 +48,9 @@ If we ever need to change the message or the way it is shown -- it's enough to m ## Local variables -A function may declare *local* variables with `var`, `let` or `const`. +A variable declared inside a function is only visible inside that function. -These variables are only seen from inside the function: +For example: ```js //+ run @@ -67,121 +67,95 @@ showMessage(); // Hello, I'm JavaScript! alert( message ); // <-- Error! The variable is local to the function ``` +## Outer variables - -**Блоки `if/else`, `switch`, `for`, `while`, `do..while` не влияют на область видимости переменных.** - -При объявлении переменной в таких блоках, она всё равно будет видна во всей функции. - -Например: - -```js -//+ no-beautify -function count() { - // переменные i,j не будут уничтожены по окончании цикла - for (*!*var*/!* i = 0; i < 3; i++) { - *!*var*/!* j = i * 2; - } - -*!* - alert( i ); // i=3, последнее значение i, при нём цикл перестал работать - alert( j ); // j=4, последнее значение j, которое вычислил цикл -*/!* -} -``` - -**Неважно, где именно в функции и сколько раз объявляется переменная. Любое объявление срабатывает один раз и распространяется на всю функцию.** - -Объявления переменных в примере выше можно передвинуть вверх, это ни на что не повлияет: - -```js -function count() { -*!* - var i, j; // передвинули объявления var в начало -*/!* - for (i = 0; i < 3; i++) { - j = i * 2; - } - - alert( i ); // i=3 - alert( j ); // j=4 -} -``` - -## Внешние переменные - -Функция может обратиться ко внешней переменной, например: +A function can access an outer variable as well, for example: ```js //+ run no-beautify -var *!*userName*/!* = 'Вася'; +var *!*userName*/!* = 'John'; function showMessage() { - var message = 'Привет, я ' + *!*userName*/!*; + var message = 'Hello, my name is ' + *!*userName*/!*; alert(message); } -showMessage(); // Привет, я Вася +showMessage(); // Hello, my name is John ``` -Доступ возможен не только на чтение, но и на запись. При этом, так как переменная внешняя, то изменения будут видны и снаружи функции: +The function can not only read but also modify an outer variable. + +For instance: ```js //+ run -var userName = 'Вася'; +var *!*userName*/!* = 'John'; function showMessage() { - userName = 'Петя'; // (1) присвоение во внешнюю переменную + userName = "Bob"; // (1) changed the outer variable - var message = 'Привет, я ' + userName; - alert( message ); + var message = 'Hello, my name is ' + *!*userName*/!*; + alert(message); } +alert( userName ); // John before the function call + showMessage(); *!* -alert( userName ); // Петя, значение внешней переменной изменено функцией +alert( userName ); // Bob, the value was modified by the function */!* ``` -Конечно, если бы внутри функции, в строке `(1)`, была бы объявлена своя локальная переменная `var userName`, то все обращения использовали бы её, и внешняя переменная осталась бы неизменной. +Of course if we had `var userName = ...` in the line (1) then the function would have a local variable `userName` and use it instead of the outer one: -**Переменные, объявленные на уровне всего скрипта, называют *"глобальными переменными"*.** +```js +//+ run +var *!*userName*/!* = 'John'; -В примере выше переменная `userName` -- глобальная. +function showMessage() { +*!* + var userName = "Bob"; // declare a local variable +*/!* -Делайте глобальными только те переменные, которые действительно имеют общее значение для вашего проекта, а нужные для решения конкретной задачи -- пусть будут локальными в соответствующей функции. + var message = 'Hello, my name is ' + *!*userName*/!*; + alert(message); +} +// the function will create and use it's own userName +showMessage(); -[warn header="Внимание: неявное объявление глобальных переменных!"] +*!* +alert( userName ); // John, the outer variable is not modified +*/!* +``` -В старом стандарте JavaScript существовала возможность неявного объявления переменных присвоением значения. +**Variables declared on the most outer level, not in any function, are called *global*.** -Например: +Please only declare global the variables which have a project-wide importance. Variables needed by specific tasks should reside in the corresponding functions. So to say, global variables are rare in modern projects. + +[warn header="Attention: implicit global declaration!"] +In the old JavaScript it was possible to omit variable declaration: ```js //+ run function showMessage() { - message = 'Привет'; // без var! + message = 'Hello'; // pure assignment, no declaration } showMessage(); -alert( message ); // Привет +alert( message ); // Hello ``` -В коде выше переменная `message` нигде не объявлена, а сразу присваивается. Скорее всего, программист просто забыл поставить `var`. +In the code above `message` was not declared. Most probably, the programmer simply forgot to write `var`. -При `use strict` такой код привёл бы к ошибке, но без него переменная будет создана автоматически, причём в примере выше она создаётся не в функции, а на уровне всего скрипта. +With `"use strict"` there will be an error. But without it, the variable will be created automatically. And not in the function, but globally, in the whole script. -Избегайте этого. - -Здесь опасность даже не в автоматическом создании переменной, а в том, что глобальные переменные должны использоваться тогда, когда действительно нужны "общескриптовые" параметры. - -Забыли `var` в одном месте, потом в другом -- в результате одна функция неожиданно поменяла глобальную переменную, которую использует другая. И поди разберись, кто и когда её поменял, не самая приятная ошибка для отладки. +Modern editors and tools for code quality checking like [jshint](http://jshint.com/) allow to see and fix "missed declarations" early while coding. [/warn] -В будущем, когда мы лучше познакомимся с основами JavaScript, в главе [](/closures), мы более детально рассмотрим внутренние механизмы работы переменных и функций. +In the future, after we deal with the basics and data structures, in the chapter [](/closures) we will go deeper in the internals of functions and variables. ## Параметры diff --git a/figures.sketch b/figures.sketch index c5d07de6..77fece17 100644 Binary files a/figures.sketch and b/figures.sketch differ