diff --git a/1-js/1-getting-started/1-intro/limitations.png b/1-js/1-getting-started/1-intro/limitations.png index 0f58b9d6..70c3f75a 100644 Binary files a/1-js/1-getting-started/1-intro/limitations.png and b/1-js/1-getting-started/1-intro/limitations.png differ diff --git a/1-js/1-getting-started/1-intro/limitations@2x.png b/1-js/1-getting-started/1-intro/limitations@2x.png index e790016b..32cb0d81 100644 Binary files a/1-js/1-getting-started/1-intro/limitations@2x.png and b/1-js/1-getting-started/1-intro/limitations@2x.png differ diff --git a/1-js/2-first-steps/12-ifelse/2-check-standard/ifelse_task2.png b/1-js/2-first-steps/12-ifelse/2-check-standard/ifelse_task2.png index 755b5f8f..9b05ed37 100644 Binary files a/1-js/2-first-steps/12-ifelse/2-check-standard/ifelse_task2.png and b/1-js/2-first-steps/12-ifelse/2-check-standard/ifelse_task2.png differ diff --git a/1-js/2-first-steps/12-ifelse/2-check-standard/ifelse_task2@2x.png b/1-js/2-first-steps/12-ifelse/2-check-standard/ifelse_task2@2x.png index eef14c2e..e02f892c 100644 Binary files a/1-js/2-first-steps/12-ifelse/2-check-standard/ifelse_task2@2x.png and b/1-js/2-first-steps/12-ifelse/2-check-standard/ifelse_task2@2x.png differ diff --git a/1-js/2-first-steps/12-ifelse/4-check-login/ifelse_task.png b/1-js/2-first-steps/12-ifelse/4-check-login/ifelse_task.png index 1867bf7c..43fe70e2 100644 Binary files a/1-js/2-first-steps/12-ifelse/4-check-login/ifelse_task.png and b/1-js/2-first-steps/12-ifelse/4-check-login/ifelse_task.png differ diff --git a/1-js/2-first-steps/12-ifelse/4-check-login/ifelse_task@2x.png b/1-js/2-first-steps/12-ifelse/4-check-login/ifelse_task@2x.png index 9128017a..d639a099 100644 Binary files a/1-js/2-first-steps/12-ifelse/4-check-login/ifelse_task@2x.png and b/1-js/2-first-steps/12-ifelse/4-check-login/ifelse_task@2x.png differ 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 24391c1d..69fa2bcf 100644 --- a/1-js/2-first-steps/18-function-basics/article.md +++ b/1-js/2-first-steps/18-function-basics/article.md @@ -121,7 +121,7 @@ let userName = 'John'; function showMessage() { *!* - let userName = "Bob"; // declare a local variable + let userName = "Bob"; // declare a local variable */!* let message = 'Hello, my name is ' + userName; @@ -137,16 +137,16 @@ alert( userName ); // John, the function did not access the outer variable ``` [smart header="Global variables"] -Variables declared outside of any function, are called *global*. +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. +Global variables are visible from any function. -They should be only used to store the data of project-wide importance. Variables needed by specific tasks should reside in the corresponding functions. +They should only be used if the data is so important that it really must be seen from anywhere. [/smart] ## Parameters -We can pass arbitrary data to the function using it's parameters (also called *function arguments*) . +We can pass arbitrary data to function using it's parameters (also called *function arguments*) . In the example below, the function has two parameters: `from` and `text`. @@ -374,7 +374,7 @@ Few examples of breaking this rule: [/smart] @@ -384,7 +384,7 @@ Functions that are used *very often* sometimes have ultrashort names. For example, [jQuery](http://jquery.com) framework defines a function `$`, [LoDash](http://lodash.com/) library has it's core function named `_`. -These are exceptions though. Generally the functions names should be concise, but descriptive. +These are exceptions. Generally functions names should be concise, but descriptive. [/smart] diff --git a/1-js/2-first-steps/18-function-basics/function_basics.png b/1-js/2-first-steps/18-function-basics/function_basics.png index ce18bdb3..14822de3 100644 Binary files a/1-js/2-first-steps/18-function-basics/function_basics.png and b/1-js/2-first-steps/18-function-basics/function_basics.png differ diff --git a/1-js/2-first-steps/18-function-basics/function_basics@2x.png b/1-js/2-first-steps/18-function-basics/function_basics@2x.png index 6f24f030..ad599134 100644 Binary files a/1-js/2-first-steps/18-function-basics/function_basics@2x.png and b/1-js/2-first-steps/18-function-basics/function_basics@2x.png differ diff --git a/1-js/2-first-steps/19-function-declaration-expression/article.md b/1-js/2-first-steps/19-function-declaration-expression/article.md deleted file mode 100644 index fc809d85..00000000 --- a/1-js/2-first-steps/19-function-declaration-expression/article.md +++ /dev/null @@ -1,263 +0,0 @@ -# Function expressions - -Function Expression is analternative syntax for creating a function. - -It looks like this: - -```js -//+ run -let func = function(parameters) { - // body -}; -``` - -For instance: - -```js -//+ run -let sayHi = function(person) { - alert( `Hello, ${person}` ); -}; - -sayHi('John'); // Hello, John -``` - -The function created in the example above is fully functional and identical to: - -```js -function sayHi(person) { - alert( `Hello, ${person}` ); -} -``` - -## Function is a value - -Function Expressions clearly demonstrate one simple thing. - -**In JavaScript, function is a kind of a value.** - -We can declare it as we did before: - -```js -function sayHi() { - alert( "Hello" ); -} -``` - -...Or as a function expression: - -```js -let sayHi = function() { - alert( "Hello" ); -} -``` - -The meaning of these lines is the same: create a function, put it into the variable `sayHi`. - -Yes, no matter, how it is defined -- it's just a value. - -We can even show it using `alert`: - -```js -//+ run -function sayHi() { - alert( "Hello" ); -} - -*!* -alert( sayHi ); // shows the function code -*/!* -``` - -Note that there are no brackets after `sayHi` in the last line. The function is not called there. Instead the `alert` shows it's string representation, that is the source code. - -As the function is a value, we can also copy it to another variable: - -```js -//+ run no-beautify -function sayHi() { // (1) create - alert( "Hello" ); -} - -let func = sayHi; // (2) copy -func(); // Hello // (3) callable! - -sayHi = null; // (4) kill old -sayHi(); // error! (null now) -``` - -
    -
  1. Function declaration `(1)` creates the function and puts it into the variable `sayHi`"
  2. -
  3. Line `(2)` copies it into variable `func`. - -Please note again: there are no brackets after `sayHi`. If they were, then the call `let func = sayHi()` would write a *result* of `sayHi()` into `func`, not the function itself.
  4. -
  5. At the moment `(3)` the function can be called both as `sayHi()` and `func()`.
  6. -
  7. ...We can overwrite `sayHi` easily. As well as `func`, they are normal variables. Naturally, the call attempt would fail in the case `(4)`.
  8. -
- -Again, it does not matter how to create a function here. If we change the first line above into a Function Expression: `let sayHi = function() {`, everything would be the same. - -[smart header="A function is a value representing an \"action\""] -Regular values like strings or numbers represent the *data*. - -A function can be perceived as an *action*. - -We can copy it between variables and run when we want. -[/smart] - - -## Comparison with Function Declaration - -The "classic" syntax of the function that looks like `function name(params) {...}` is called a "Function Declaration". - -We can formulate the following distinction: - - -The main difference between them is the creation time. - - - -In other words, when JavaScript prepares to run the code block, it looks for Function Declarations in it and creates the functions. We can think of it as an "initialization stage". Then it runs the code. And while the code is running, Function Expressions can be created. - -As a side-effect, functions declared as Function Declaration can be called earlier than they are defined. - -For instance, this works: - -```js -//+ run refresh untrusted -*!* -sayHi("John"); // Hello, John -*/!* - -function sayHi(name) { - alert( `Hello, ${name}` ); -} -``` - -...And if there were Function Expression, then it wouldn't work: - -```js -//+ run refresh untrusted -*!* -sayHi("John"); // error! -*/!* - -let sayHi = function(name) { // (*) - alert( `Hello, ${name}` ); -}; -``` - -Function Expressions are created in the process of evaluation of the expression with them. So, in the code above, the function is created and assigned to `sayHi` only when the execution reaches the line `(*)`. - -Usually, a Function Declaration is preferable because of that. It gives more freedom in how to organize our code. - -## Anonymous functions - -As a function is a value, it can be created on-demand and passed to another place of the code. - -For instance, let's consider the following real-life task. - -Function `ask(question, yes, no)` should accept a question and two other functions: `yes` and `no`. It asks a question and, if the user responds positively, executes `yes()`, otherwise `no()`. - -It could look like this: -```js -//+ run -function ask(question, yes, no) { - if (confirm(question)) yes() - else no(); -} -``` - -In real-life `ask` will be usually much more complex, because it draws a nice windows and takes care about how to preent the `question` to the user, but here we don't care about that. Just `confirm` is enough. - -So, how do we use it? - -If we had only Function Declarations in our toolbox, we could declare `showOk/showCancel` as actions and pass them: - - -```js -function showOk() { - alert( "Ok, proceeding." ); -} - -function showCancel() { - alert( "Execution canceled." ); -} - -// usage -ask("Should we proceed?", showOk, showCancel); -``` - -...But Function Expressions allow us to solve the task much more elegantly: - -```js -ask("Should we proceed?", - function() { alert( "Ok, proceeding." ); }, - function() { alert( "Execution canceled." ); }, -); -``` - -So, we can declare a function in-place, exactly when we need it. - -These functions are sometimes called "anonymous" meaning that they are defined without a name. So to say, we can't reuse this function anywhere outside of `ask`. And that's fine here. - -Creating functions in-place is very natural and in the spirit of JavaScript. - -## Summary - - - -Novice programmers sometimes overuse Function Expressions. Somewhy, maybe not quite understanding what's going on, they create functions like `let func = function()`. - -But in most cases Function Declaration is preferable. - -Compare, which one is more readable: - -```js -//+ no-beautify -// Function Expression -let f = function() { ... } - -// Function Declaration -function f() { ... } -``` - -Function Declaration is shorter and more obvious. The additional bonus -- it can be called before the declaration. - -Use Function Expression only when the function must be created at-place, inside another expression. - diff --git a/1-js/2-first-steps/19-function-expression/article.md b/1-js/2-first-steps/19-function-expression/article.md new file mode 100644 index 00000000..c8d27666 --- /dev/null +++ b/1-js/2-first-steps/19-function-expression/article.md @@ -0,0 +1,390 @@ +# Function expressions + +Function Expression is an analternative syntax for declaring a function. + +It looks like this: + +```js +//+ run +let func = function(parameters) { + // body +}; +``` + +For instance: + +```js +//+ run +let sayHi = function(person) { + alert( `Hello, ${person}` ); +}; + +sayHi('John'); // Hello, John +``` + +The function `sayHi` created in the example above is identical to: + +```js +function sayHi(person) { + alert( `Hello, ${person}` ); +} +``` + +## Function is a value + +Function Expression clearly demonstrates one simple thing. + +**In JavaScript, a function is a value.** + +We can declare it as we did before: + +```js +function sayHi() { + alert( "Hello" ); +} +``` + +...Or as a function expression: + +```js +let sayHi = function() { + alert( "Hello" ); +} +``` + +The meaning of these lines is the same: create a function, put it into the variable `sayHi`. + +Yes, no matter, how it is defined -- it's just a value, stored in the variable `sayHi`. + +We can even show it using `alert`: + +```js +//+ run +function sayHi() { + alert( "Hello" ); +} + +*!* +alert( sayHi ); // shows the function code +*/!* +``` + +Note that there are no brackets after `sayHi` in the last line. The function is not called there. Instead the `alert` shows it's string representation, that is the source code. + +As the function is a value, we can also copy it to another variable: + +```js +//+ run no-beautify +function sayHi() { // (1) create + alert( "Hello" ); +} + +let func = sayHi; // (2) copy + +func(); // Hello // (3) call the copy (it works)! + +sayHi = null; // (4) nullify the old variable +sayHi(); // error! (null now) +``` + +
    +
  1. Function declaration `(1)` creates the function and puts it into the variable `sayHi`"
  2. +
  3. Line `(2)` copies it into variable `func`. + +Please note again: there are no brackets after `sayHi`. If they were, then `func = sayHi()` would write *the result* of the call `sayHi()` into `func`, not the function `sayHi` itself.
  4. +
  5. At the moment `(3)` the function can be called both as `sayHi()` and `func()`.
  6. +
  7. ...We can overwrite `sayHi` easily. As `func`, it is a normal variable. Naturally, the call attempt would fail in the case `(4)`.
  8. +
+ +Again, it does not matter how to create a function here. If we change the first line above into a Function Expression: `let sayHi = function() {`, everything would be the same. + +[smart header="A function is a value representing an \"action\""] +Regular values like strings or numbers represent the *data*. + +A function can be perceived as an *action*. + +We can copy it between variables and run when we want. +[/smart] + + +Function Expressions are very convenient for creating an action in-place and passing it along the code. + +For instance, let's consider the following real-life task. + +Function `ask(question, yes, no)` should accept a textual `question` and two other functions: `yes` and `no`. It asks a question and, if the user responds positively, executes `yes()`, otherwise `no()`. + +It could look like this: +```js +//+ run +function ask(question, yes, no) { + if (confirm(question)) yes() + else no(); +} +``` + +In real-life `ask` would be usually much more complex, because it would draw a nice window and take care about how to present the `question` to the user etc. But here we consider the general form of such function, so `confirm` is enough. + +So, how do we use it? + +If we had only Function Declarations in our toolbox, we could declare `showOk/showCancel` and pass them: + + +```js +function showOk() { + alert( "Ok, proceeding." ); +} + +function showCancel() { + alert( "Execution canceled." ); +} + +// usage +ask("Should we proceed?", showOk, showCancel); +``` + +...But Function Expressions allow us to solve the task much more elegantly: + +```js +ask("Should we proceed?", + function() { alert( "Ok, proceeding." ); }, + function() { alert( "Execution canceled." ); }, +); +``` + +Here we can declare actions in-place, exactly when we need it. + +Such functions are sometimes called "anonymous" meaning that they are defined without a name. So to say, we can't reuse them outside of `ask`, because there is no variable for them. But for this kind of task it's exactly what we want. + +Creating functions in-place is very natural and in the spirit of JavaScript. + + +## Function Expression vs Function Declaration + +The "classic" syntax of the function that looks like `function name(params) {...}` is called a "Function Declaration". + +We can formulate the following distinction: + + +The main differences between them are visibility and creation time. + +**Function Expressions are created when the execution reaches them.** + +That's easy. Once the execution flow passes to the right side of the assignment -- here we go, the function is made and can be used (assigned, called etc) from now on. + +Function Declarations are different. They are treated in a special way. + +When JavaScript prepares to run the code block, it looks for Function Declarations in it and creates the functions. We can think of it as an "initialization stage". Then it runs the code. + +**Function Declarations are created before the code block begins to execute and is visible in the whole block.** + +If the Function Declaration is not inside a code block `{...}`, then it is created when the script starts and is visible in the whole script. All declarations in the examples above are not in the code block. + +As a natural effect, a function declared as Function Declaration can be called earlier than it is defined. + +For instance, this works: + +```js +//+ run refresh untrusted +*!* +sayHi("John"); // Hello, John +*/!* + +function sayHi(name) { + alert( `Hello, ${name}` ); +} +``` + +Function Declaration `sayHi` is created when the script starts and is visible everywhere in it. + +...And if there were Function Expression, then it wouldn't work: + +```js +//+ run refresh untrusted +*!* +sayHi("John"); // error! +*/!* + +let sayHi = function(name) { // (*) + alert( `Hello, ${name}` ); +}; +``` + +Function Expressions are created in the process of evaluation of the expression with them. So, in the code above, the function would be created and assigned to `sayHi` only when the execution reaches the line `(*)`. Too late. + +Now let's explore the visibility thing. + +Imagine, we need to declare `welcome()` depending on some data we get in run-time. + +For instance: + +```js +//+ run + +let age = prompt("What is your age?", 18); + +if (age < 18) { + + function welcome() { + alert("Hello!"); + } + +} else { + + function welcome() { + alert("Greetings!"); + } + +} + +*!* +welcome(); // Error: welcome is not defined +*/!* +``` + +In the code above, we mean to create function `welcome()` depending on the `age`. So, that it can't be called later, probably from another place of the code, in case of an event or such. + +But that doesn't work, because Function Declaration `function welcome()` is visible only inside the block where it resides. + +We can call it from within the block, but not from outside: + +```js +//+ run +let age = 15; // let's consider 15 as an example + +if (age < 18) { +*!* + welcome(); // \ (works) +*/!* + // | + function welcome() { // | + alert("Hello!"); // | available here + } // | + // | +*!* + welcome(); // / (works) +*/!* + +} else { + // \ + function welcome() { // | + alert("Greetings!"); // | available here + } // | + // / +} + +*!* +welcome(); // Error: outside of the block there's no welcome +*/!* +``` + +What can we do to fix the problem? One of the ways is to use a Function Expression and assign `welcome` to the variable which has the proper visibility: + + + +```js +//+ run + +let age = prompt("What is your age?", 18); + +let welcome; + +if (age < 18) { + + welcome = function() { + alert("Hello!"); + } + +} else { + + welcome = function() { + alert("Greetings!"); + } + +} + +*!* +welcome(); // ok now +*/!* +``` + +Or we could go on to simplify it even further using a question mark operator `?`: + +```js +//+ run + +let age = prompt("What is your age?", 18); + +let welcome = (age < 18) ? + function() { + alert("Hello!"); + } : + function() { + alert("Greetings!"); + } + +*!* +welcome(); // ok now +*/!* +``` + +[smart header="So, a Declaration or an Expression?"] +As a rule of thumb, if we want just to declare a function, then a Function Declaration is prefered. It gives more freedom in how to organize our code, because we can put "helper functions" below. It's also a little bit easier to read and look up them in the text. + +Only if a Function Declaration does not suit us for some reason, then a Function Expression should be used. +[/smart] + + +## Summary + + + +Novice programmers sometimes overuse Function Expression by creating many functions with `let func = function()`. + +But in most cases Function Declaration is preferable. + +Compare, which code is more readable: + +```js +//+ no-beautify +// Function Expression +let f = function() { ... } + +// Function Declaration +function f() { ... } +``` + +Function Declaration is shorter and more obvious. The additional bonus -- it can be called before the declaration. + +Use Function Expression only when the function must be created at-place, inside another expression. diff --git a/1-js/3-writing-js/2-coding-style/1-style-errors/solution.md b/1-js/2-first-steps/20-coding-style/1-style-errors/solution.md similarity index 100% rename from 1-js/3-writing-js/2-coding-style/1-style-errors/solution.md rename to 1-js/2-first-steps/20-coding-style/1-style-errors/solution.md diff --git a/1-js/3-writing-js/2-coding-style/1-style-errors/task.md b/1-js/2-first-steps/20-coding-style/1-style-errors/task.md similarity index 100% rename from 1-js/3-writing-js/2-coding-style/1-style-errors/task.md rename to 1-js/2-first-steps/20-coding-style/1-style-errors/task.md diff --git a/1-js/3-writing-js/2-coding-style/article.md b/1-js/2-first-steps/20-coding-style/article.md similarity index 57% rename from 1-js/3-writing-js/2-coding-style/article.md rename to 1-js/2-first-steps/20-coding-style/article.md index 571b4510..6b75e5ca 100644 --- a/1-js/3-writing-js/2-coding-style/article.md +++ b/1-js/2-first-steps/20-coding-style/article.md @@ -1,101 +1,105 @@ -# Советы по стилю кода +# Coding style -Код должен быть максимально читаемым и понятным. Для этого нужен *хороший стиль* написания кода. В этой главе мы рассмотрим компоненты такого стиля. +Our code must be as clean and easy to read as possible. + +That is actually an art of programming -- to take a complex task and describe it using a programming language in a way that is both correct and human-readable. + +One thing to help is a good code style. In this chapter we cover it's components. [cut] -## Синтаксис +## Syntax -Шпаргалка с правилами синтаксиса (детально их варианты разобраны далее): +A cheatsheep with the rules (more details below): - -Не всё здесь однозначно, так что разберём эти правила подробнее. +Nothing is "carved in stone" here, so let's discuss the rules in detail. -### Фигурные скобки +### Figure brackets -Пишутся на той же строке, так называемый "египетский" стиль. Перед скобкой -- пробел. +In most JavaScript projects figure brackets are written on the same line. A so-called "egyptian" style. There's also a space before an opening bracket. + +If the code has only one line, then there are options: - -Если у вас уже есть опыт в разработке, и вы привыкли делать скобку на отдельной строке -- это тоже вариант. В конце концов, решать вам. Но в большинстве JavaScript-фреймворков стиль именно такой. +For a real short code like `if (cond) return null`, one line is acceptable... But still a separate line for each statement is usually easier to read. -Если условие и код достаточно короткие, например `if (cond) return null`, то запись в одну строку вполне читаема... Но, как правило, отдельная строка всё равно воспринимается лучше. +### Line length -### Длина строки +Line length is limited. No one likes to eye-follow a long horizontal line. Doesn't matter if it's a text or a OR'ed list of `if` conditions. It's better to split it. -Максимальную длину строки согласовывают в команде. Как правило, это либо `80`, либо `120` символов, в зависимости от того, какие мониторы у разработчиков. +Maximal line length is agreed on the team-level. It's usually 80 or 120 characters. -Более длинные строки необходимо разбивать для улучшения читаемости. +### Indents -### Отступы - -Отступы нужны двух типов: +There are two types of indents: -### Точка с запятой +### A semicolon -Точки с запятой нужно ставить, даже если их, казалось бы, можно пропустить. +Semicolons must be after each statement. Even if could possiblty be skipped. -Есть языки, в которых точка с запятой не обязательна, и её там никто не ставит. В JavaScript перевод строки её заменяет, но лишь частично, поэтому лучше её ставить, как обсуждалось [ранее](#semicolon). +There are languages where a semicolon is truly optional. It's rarely used there. -## Именование +But in JavaScript a line break is sometimes interpreted as a semicolon and sometimes not. That leaves a place for programming errors, so semicolons must be at place, just as discussed [before](#semicolon). + +## The Naming + +The general rule: -Общее правило: -Для имён используется английский язык (не транслит) и верблюжья нотация. +English language and camel-case notation is used. -Более подробно -- читайте про [имена функций](#function-naming) и [имена переменных](#variable-naming). +Also discussed before -- [function naming](#function-naming) and [variables naming](#variable-naming). -## Уровни вложенности +## Nesting levels -Уровней вложенности должно быть немного. +There should not be too many nesting levels. -Например, [проверки в циклах можно делать через "continue"](#continue), чтобы не было дополнительного уровня `if(..) { ... }`: +Sometimes it's a good idea to [use the "continue"](#continue) directive in the loop to evade extra nesting in `if(..) { ... }`: -Вместо: +Instead of: ```js -for (var i = 0; i < 10; i++) { - if (i подходит) { - ... // <- уровень вложенности 2 +for (let i = 0; i < 10; i++) { + if (cond) { + ... // <- one more nesting level } } ``` -Используйте: +We can write: ```js -for (var i = 0; i < 10; i++) { - if (i *!*не*/!* подходит) *!*continue*/!*; - ... // <- уровень вложенности 1 +for (let i = 0; i < 10; i++) { + if (!cond) *!*continue*/!*; + ... // <- no extra nesting level } ``` -Аналогичная ситуация -- с `if/else` и `return`. Следующие две конструкции идентичны. +The similar thing can be done with `if/else` and `return`. -Первая: +For example, two constructs below are identical. + +The first one: ```js -function isEven(n) { // проверка чётности +function isEven(n) { // returns whether the number is even if (n % 2 == 0) { return true; *!* @@ -166,10 +175,10 @@ function isEven(n) { // проверка чётности } ``` -Вторая: +The second one: ```js -function isEven(n) { // проверка чётности +function isEven(n) { if (n % 2 == 0) { return true; } @@ -180,33 +189,33 @@ function isEven(n) { // проверка чётности } ``` -Если в блоке `if` идёт `return`, то `else` за ним не нужен. +If there's a `return` inside the `if` block, then we need no `else` after it. -**Лучше быстро обработать простые случаи, вернуть результат, а дальше разбираться со сложным, без дополнительного уровня вложенности.** - -В случае с функцией `isEven` можно было бы поступить и проще: +...Of course we can write even shorter here: ```js -function isEven(n) { // проверка чётности +function isEven(n) { return !(n % 2); } ``` -...Однако, если код `!(n % 2)` для вас менее очевиден чем предыдущий вариант, то стоит использовать предыдущий. +...But if the code `!(n % 2)` is less obvious for you than the former variant then use the former one. -Главное для нас -- не краткость кода, а его простота и читаемость. Совсем не всегда более короткий код проще для понимания, чем более развёрнутый. +**The most important for us is not shortness, but simplicity and readability of the code.** -## Функции = Комментарии +It's quite not always the case that a brief code is simpler to understand. -Функции должны быть небольшими. Если функция большая -- желательно разбить её на несколько. +## Functions = Comments -Этому правилу бывает сложно следовать, но оно стоит того. При чем же здесь комментарии? +Functions should be short and do exactly one thing. If that thing is big, maybe it's worth to split the function into parts. -Вызов отдельной небольшой функции не только легче отлаживать и тестировать -- сам факт его наличия является *отличным комментарием*. +Sometimes following this rule may be not easy, but it's a definitely good thing. So what's with the comments? -Сравните, например, две функции `showPrimes(n)` для вывода простых чисел до `n`. +A separate function is not only easier to test and debug -- it's very existance is a great comment. -Первый вариант использует метку: +For instance, compare the two functions `showPrimes(n)` below. Each one outputs [prime numbers](https://en.wikipedia.org/wiki/Prime_number) up to `n`. + +The first variant uses a label: ```js function showPrimes(n) { @@ -216,42 +225,42 @@ function showPrimes(n) { if (i % j == 0) continue nextPrime; } - alert( i ); // простое + alert( i ); // a prime } } ``` -Второй вариант -- дополнительную функцию `isPrime(n)` для проверки на простоту: +The second variant uses an additional function `isPrime(n)` to test primality: ```js function showPrimes(n) { - for (var i = 2; i < n; i++) { + for (let i = 2; i < n; i++) { *!*if (!isPrime(i)) continue;*/!* - alert(i); // простое + alert(i); // a prime } } function isPrime(n) { - for (var i = 2; i < n; i++) { + for (let i = 2; i < n; i++) { if ( n % i == 0) return false; } return true; } ``` -Второй вариант проще и понятнее, не правда ли? Вместо участка кода мы видим описание действия, которое там совершается (проверка `isPrime`). - -## Функции -- под кодом +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*. -Есть два способа расположить функции, необходимые для выполнения кода. +## Functions below the code + +There are three way to place the "helper" functions used in the code.
    -
  1. Функции над кодом, который их использует: +
  2. Above the code that uses them: ```js -// *!*объявить функции*/!* +// *!*function declarations*/!* function createElement() { ... } @@ -264,22 +273,22 @@ function walkAround() { ... } -// *!*код, использующий функции*/!* +// *!*the code which uses them*/!* var elem = createElement(); setHandler(elem); walkAround(); ```
  3. -
  4. Сначала код, а функции внизу: +
  5. Code first, then functions ```js -// *!*код, использующий функции*/!* +// *!*the code which uses the functions*/!* var elem = createElement(); setHandler(elem); walkAround(); -// --- *!*функции*/!* --- +// --- *!*helper functions*/!* --- function createElement() { ... @@ -295,17 +304,14 @@ function walkAround() { ```
  6. +
  7. Mixed, a function is described when it's first used.
-...На самом деле существует еще третий "стиль", при котором функции хаотично разбросаны по коду, но это ведь не наш метод, да? +Most of time, the second variant is preferred. -**Как правило, лучше располагать функции под кодом, который их использует.** +That's because when reading a code, we first want to know "what it does". If the code goes first, then it provides that information. And then maybe we won't need to read functions at all, especially if their names are adequate to what they're doing. -То есть, предпочтителен 2й способ. - -Дело в том, что при чтении такого кода мы хотим знать в первую очередь, *что он делает*, а уже затем *какие функции ему помогают.* Если первым идёт код, то это как раз дает необходимую информацию. Что же касается функций, то вполне возможно нам и не понадобится их читать, особенно если они названы адекватно и то, что они делают, понятно из названия. - -## Плохие комментарии +## Bad comments В коде нужны комментарии. diff --git a/1-js/2-first-steps/20-coding-style/code-style.png b/1-js/2-first-steps/20-coding-style/code-style.png new file mode 100644 index 00000000..b59ca375 Binary files /dev/null and b/1-js/2-first-steps/20-coding-style/code-style.png differ diff --git a/1-js/2-first-steps/20-coding-style/code-style@2x.png b/1-js/2-first-steps/20-coding-style/code-style@2x.png new file mode 100644 index 00000000..050bac93 Binary files /dev/null and b/1-js/2-first-steps/20-coding-style/code-style@2x.png differ diff --git a/1-js/2-first-steps/20-coding-style/figure-bracket-style.png b/1-js/2-first-steps/20-coding-style/figure-bracket-style.png new file mode 100644 index 00000000..f5726667 Binary files /dev/null and b/1-js/2-first-steps/20-coding-style/figure-bracket-style.png differ diff --git a/1-js/2-first-steps/20-coding-style/figure-bracket-style@2x.png b/1-js/2-first-steps/20-coding-style/figure-bracket-style@2x.png new file mode 100644 index 00000000..ca0ef8d9 Binary files /dev/null and b/1-js/2-first-steps/20-coding-style/figure-bracket-style@2x.png differ diff --git a/1-js/2-first-steps/20-recursion/1-sum-to/solution.md b/1-js/2-first-steps/20-recursion/1-sum-to/solution.md deleted file mode 100644 index 57d2c572..00000000 --- a/1-js/2-first-steps/20-recursion/1-sum-to/solution.md +++ /dev/null @@ -1,45 +0,0 @@ -Решение **с использованием цикла**: - -```js -//+ run -function sumTo(n) { - let sum = 0; - for let i = 1; i <= n; i++) { - sum += i; - } - return sum; -} - -alert( sumTo(100) ); -``` - -Решение через **рекурсию**: - -```js -//+ run -function sumTo(n) { - if (n == 1) return 1; - return n + sumTo(n - 1); -} - -alert( sumTo(100) ); -``` - -Решение **по формуле**: `sumTo(n) = n*(n+1)/2`: - -```js -//+ run -function sumTo(n) { - return n * (n + 1) / 2; -} - -alert( sumTo(100) ); -``` - -P.S. Надо ли говорить, что решение по формуле работает быстрее всех? Это очевидно. Оно использует всего три операции для любого `n`, а цикл и рекурсия требуют как минимум `n` операций сложения. - -Вариант с циклом -- второй по скорости. Он быстрее рекурсии, так как операций сложения столько же, но нет дополнительных вычислительных затрат на организацию вложенных вызовов. - -Рекурсия в данном случае работает медленнее всех. - -P.P.S. Существует ограничение глубины вложенных вызовов, поэтому рекурсивный вызов `sumTo(100000)` выдаст ошибку. diff --git a/1-js/2-first-steps/20-recursion/1-sum-to/task.md b/1-js/2-first-steps/20-recursion/1-sum-to/task.md deleted file mode 100644 index 9e7e8e8f..00000000 --- a/1-js/2-first-steps/20-recursion/1-sum-to/task.md +++ /dev/null @@ -1,34 +0,0 @@ -# Вычислить сумму чисел до данного - -[importance 5] - -Напишите функцию `sumTo(n)`, которая для данного `n` вычисляет сумму чисел от 1 до `n`, например: - -```js -//+ no-beautify -sumTo(1) = 1 -sumTo(2) = 2 + 1 = 3 -sumTo(3) = 3 + 2 + 1 = 6 -sumTo(4) = 4 + 3 + 2 + 1 = 10 -... -sumTo(100) = 100 + 99 + ... + 2 + 1 = 5050 -``` - -Сделайте три варианта решения: -
    -
  1. С использованием цикла.
  2. -
  3. Через рекурсию, т.к. `sumTo(n) = n + sumTo(n-1)` для `n > 1`.
  4. -
  5. С использованием формулы для суммы [арифметической прогрессии](http://ru.wikipedia.org/wiki/%D0%90%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B5%D1%81%D1%81%D0%B8%D1%8F).
  6. -
- -Пример работы вашей функции: - -```js -function sumTo(n) { /*... ваш код ... */ } - -alert( sumTo(100) ); // 5050 -``` - -**Какой вариант решения самый быстрый? Самый медленный? Почему?** - -**Можно ли при помощи рекурсии посчитать `sumTo(100000)`? Если нет, то почему?** diff --git a/1-js/2-first-steps/20-recursion/2-factorial/solution.md b/1-js/2-first-steps/20-recursion/2-factorial/solution.md deleted file mode 100644 index f3811e2c..00000000 --- a/1-js/2-first-steps/20-recursion/2-factorial/solution.md +++ /dev/null @@ -1,25 +0,0 @@ -По свойствам факториала, как описано в условии, `n!` можно записать как `n * (n-1)!`. - -То есть, результат функции для `n` можно получить как `n`, умноженное на результат функции для `n-1`, и так далее до `1!`: - -```js -//+ run -function factorial(n) { - return (n != 1) ? n * factorial(n - 1) : 1; -} - -alert( factorial(5) ); // 120 -``` - -Базисом рекурсии является значение `1`. А можно было бы сделать базисом и `0`. Тогда код станет чуть короче: - -```js -//+ run -function factorial(n) { - return n ? n * factorial(n - 1) : 1; -} - -alert( factorial(5) ); // 120 -``` - -В этом случае вызов `factorial(1)` сведётся к `1*factorial(0)`, будет дополнительный шаг рекурсии. diff --git a/1-js/2-first-steps/20-recursion/2-factorial/task.md b/1-js/2-first-steps/20-recursion/2-factorial/task.md deleted file mode 100644 index 59579043..00000000 --- a/1-js/2-first-steps/20-recursion/2-factorial/task.md +++ /dev/null @@ -1,29 +0,0 @@ -# Вычислить факториал - -[importance 4] - -*Факториа́л числа* -- это число, умноженное на "себя минус один", затем на "себя минус два" и так далее, до единицы. Обозначается `n!` - -Определение факториала можно записать как: - -```js -n! = n * (n - 1) * (n - 2) * ...*1 -``` - -Примеры значений для разных `n`: - -```js -1! = 1 -2! = 2 * 1 = 2 -3! = 3 * 2 * 1 = 6 -4! = 4 * 3 * 2 * 1 = 24 -5! = 5 * 4 * 3 * 2 * 1 = 120 -``` - -Задача -- написать функцию `factorial(n)`, которая возвращает факториал числа `n!`, используя рекурсивный вызов. - -```js -alert( factorial(5) ); // 120 -``` - -Подсказка: обратите внимание, что `n!` можно записать как `n * (n-1)!`. Например: `3! = 3*2! = 3*2*1! = 6` diff --git a/1-js/2-first-steps/20-recursion/3-fibonacci-numbers/solution.md b/1-js/2-first-steps/20-recursion/3-fibonacci-numbers/solution.md deleted file mode 100644 index af6fc504..00000000 --- a/1-js/2-first-steps/20-recursion/3-fibonacci-numbers/solution.md +++ /dev/null @@ -1,99 +0,0 @@ -# Вычисление рекурсией (медленное) - -Решение по формуле, используя рекурсию: - -```js -//+ run -function fib(n) { - return n <= 1 ? n : fib(n - 1) + fib(n - 2); -} - -alert( fib(3) ); // 2 -alert( fib(7) ); // 13 -// fib(77); // не запускаем, подвесит браузер -``` - -При больших значениях `n` оно будет работать очень медленно. Например, `fib(77)` уже будет вычисляться очень долго. - -Это потому, что функция порождает обширное дерево вложенных вызовов. При этом ряд значений вычисляется много раз. Например, посмотрим на отрывок вычислений: - -```js -//+ no-beautify -... -fib(5) = fib(4) + fib(3) -fib(4) = fib(3) + fib(2) -... -``` - -Здесь видно, что значение `fib(3)` нужно одновременно и для `fib(5)` и для `fib(4)`. В коде оно будет вычислено два раза, совершенно независимо. - -Можно это оптимизировать, запоминая уже вычисленные значения, получится гораздо быстрее. Альтернативный вариант -- вообще отказаться от рекурсии, а вместо этого в цикле начать с первых значений `1`, `2`, затем из них получить `fib(3)`, далее `fib(4)`, затем `fib(5)` и так далее, до нужного значения. - -Это решение будет наиболее эффективным. Попробуйте его написать. - -# Алгоритм вычисления в цикле - -Будем идти по формуле слева-направо: - -```js -//+ no-beautify -let a = 1, b = 1; // начальные значения -let c = a + b; // 2 - -/* переменные на начальном шаге: -a b c -1, 1, 2 -*/ -``` - -Теперь следующий шаг, присвоим `a` и `b` текущие 2 числа и получим новое следующее в `c`: - -```js -//+ no-beautify -a = b, b = c; -c = a + b; - -/* стало так (ещё число): - a b c -1, 1, 2, 3 -*/ -``` - -Следующий шаг даст нам ещё одно число последовательности: - -```js -//+ no-beautify -a = b, b = c; -c = a + b; - -/* стало так (ещё число): - a b c -1, 1, 2, 3, 5 -*/ -``` - -Повторять в цикле до тех пор, пока не получим нужное значение. Это гораздо быстрее, чем рекурсия, хотя бы потому что ни одно из чисел не вычисляется дважды. - -P.S. Этот подход к вычислению называется [динамическое программирование снизу-вверх](http://ru.wikipedia.org/wiki/%D0%94%D0%B8%D0%BD%D0%B0%D0%BC%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5). - -# Код для вычисления в цикле - -```js -//+ run -function fib(n) { - let a = 1, - b = 1; - for let i = 3; i <= n; i++) { - let c = a + b; - a = b; - b = c; - } - return b; -} - -alert( fib(3) ); // 2 -alert( fib(7) ); // 13 -alert( fib(77) ); // 5527939700884757 -``` - -Цикл здесь начинается с `i=3`, так как первое и второе числа Фибоначчи заранее записаны в переменные `a=1`, `b=1`. diff --git a/1-js/2-first-steps/20-recursion/3-fibonacci-numbers/task.md b/1-js/2-first-steps/20-recursion/3-fibonacci-numbers/task.md deleted file mode 100644 index b05734a0..00000000 --- a/1-js/2-first-steps/20-recursion/3-fibonacci-numbers/task.md +++ /dev/null @@ -1,24 +0,0 @@ -# Числа Фибоначчи - -[importance 5] - -Последовательность [чисел Фибоначчи](http://ru.wikipedia.org/wiki/%D0%A7%D0%B8%D1%81%D0%BB%D0%B0_%D0%A4%D0%B8%D0%B1%D0%BE%D0%BD%D0%B0%D1%87%D1%87%D0%B8) имеет формулу Fn = Fn-1 + Fn-2. То есть, следующее число получается как сумма двух предыдущих. - -Первые два числа равны `1`, затем `2(1+1)`, затем `3(1+2)`, `5(2+3)` и так далее: `1, 1, 2, 3, 5, 8, 13, 21...`. - -Числа Фибоначчи тесно связаны с [золотым сечением](http://ru.wikipedia.org/wiki/%D0%97%D0%BE%D0%BB%D0%BE%D1%82%D0%BE%D0%B5_%D1%81%D0%B5%D1%87%D0%B5%D0%BD%D0%B8%D0%B5) и множеством природных явлений вокруг нас. - -Напишите функцию `fib(n)`, которая возвращает `n-е` число Фибоначчи. Пример работы: - -```js -//+ no-beautify -function fib(n) { /* ваш код */ } - -alert( fib(3) ); // 2 -alert( fib(7) ); // 13 -alert( fib(77)); // 5527939700884757 -``` - -**Все запуски функций из примера выше должны срабатывать быстро.** - - \ No newline at end of file diff --git a/1-js/2-first-steps/21-named-function-expression/1-nfe-check/solution.md b/1-js/2-first-steps/21-named-function-expression/1-nfe-check/solution.md deleted file mode 100644 index 5875fae8..00000000 --- a/1-js/2-first-steps/21-named-function-expression/1-nfe-check/solution.md +++ /dev/null @@ -1,21 +0,0 @@ -**Первый код выведет `function ...`, второй -- ошибку во всех браузерах, кроме IE8-.** - -```js -//+ run untrusted no-beautify -// обычное объявление функции (Function Declaration) -function g() { return 1; }; - -alert(g); // функция -``` - -Во втором коде скобки есть, значит функция внутри является не `Function Declaration`, а частью выражения, то есть `Named Function Expression`. Его имя видно только внутри, снаружи переменная `g` не определена. - -```js -//+ run untrusted no-beautify -// Named Function Expression! -(function g() { return 1; }); - -alert(g); // Ошибка! -``` - -Все браузеры, кроме IE8-, поддерживают это ограничение видимости и выведут ошибку, `"undefined variable"`. \ No newline at end of file diff --git a/1-js/2-first-steps/21-named-function-expression/1-nfe-check/task.md b/1-js/2-first-steps/21-named-function-expression/1-nfe-check/task.md deleted file mode 100644 index 0510ff4d..00000000 --- a/1-js/2-first-steps/21-named-function-expression/1-nfe-check/task.md +++ /dev/null @@ -1,22 +0,0 @@ -# Проверка на NFE - -[importance 5] - -Каков будет результат выполнения кода? - -```js -//+ no-beautify -function g() { return 1; } - -alert(g); -``` - -А такого? Будет ли разница, если да -- почему? - -```js -//+ no-beautify -(function g() { return 1; }); - -alert(g); -``` - diff --git a/1-js/2-first-steps/21-named-function-expression/article.md b/1-js/2-first-steps/21-named-function-expression/article.md deleted file mode 100644 index 4d0b182e..00000000 --- a/1-js/2-first-steps/21-named-function-expression/article.md +++ /dev/null @@ -1,147 +0,0 @@ -# Именованные функциональные выражения - -Специально для работы с рекурсией в JavaScript существует особое расширение функциональных выражений, которое называется "Named Function Expression" (сокращённо NFE) или, по-русски, *"именованное функциональное выражение"*. - -[cut] - - -## Named Function Expression [#functions-nfe] - -Обычное функциональное выражение: -```js -let f = function(...) { /* тело функции */ }; -``` - -Именованное с именем `sayHi`: - -```js -//+ no-beautify -let f = function *!*sayHi*/!*(...) { /* тело функции */ }; -``` - -Что же это за имя, которое идёт в дополнение к `f`, и зачем оно? - -Имя функционального выражения (`sayHi`) имеет особый смысл. Оно доступно только изнутри самой функции. - -Это ограничение видимости входит в стандарт JavaScript и поддерживается всеми браузерами, кроме IE8-. - -Например: - -```js -//+ run -let f = function sayHi(name) { - alert( sayHi ); // изнутри функции - видно (выведет код функции) -}; - -alert( sayHi ); // снаружи - не видно (ошибка: undefined variable 'sayHi') -``` - -Кроме того, имя NFE нельзя перезаписать: - -```js -//+ run -let test = function sayHi(name) { -*!* - sayHi = "тест"; // попытка перезаписи -*/!* - alert( sayHi ); // function... (перезапись не удалась) -}; - -test(); -``` - -В режиме `use strict` код выше выдал бы ошибку. - -Как правило, имя NFE используется для единственной цели -- позволить изнутри функции вызвать саму себя. - -## Пример использования - -NFE используется в первую очередь в тех ситуациях, когда функцию нужно передавать в другое место кода или перемещать из одной переменной в другую. - -**Внутреннее имя позволяет функции надёжно обращаться к самой себе, где бы она ни находилась.** - -Вспомним, к примеру, функцию-факториал из задачи [](/task/factorial): - -```js -//+ run -function f(n) { - return n ? n * f(n - 1) : 1; -}; - -alert( f(5) ); // 120 -``` - -Попробуем перенести её в другую переменную `g`: - -```js -//+ run -function f(n) { - return n ? n * f(n - 1) : 1; -}; - -*!* -let g = f; -f = null; -*/!* - -alert( g(5) ); // запуск функции с новым именем - ошибка при выполнении! -``` - -Ошибка возникла потому что функция из своего кода обращается к своему старому имени `f`. А этой функции уже нет, `f = null`. - -Для того, чтобы функция всегда надёжно работала, объявим её как Named Function Expression: - -```js -//+ run no-beautify -let f = function *!*factorial*/!*(n) { - return n ? n**!*factorial*/!*(n-1) : 1; -}; - -let g = f; // скопировали ссылку на функцию-факториал в g -f = null; - -*!* -alert( g(5) ); // 120, работает! -*/!* -``` - -[warn header="В браузере IE8- создаются две функции"] - -Как мы говорили выше, в браузере IE до 9 версии имя NFE видно везде, что является ошибкой с точки зрения стандарта. - -...Но на самом деле ситуация ещё забавнее. Старый IE создаёт в таких случаях целых две функции: одна записывается в переменную `f`, а вторая -- в переменную `factorial`. - -Например: - -```js -//+ run -let f = function factorial(n) { /*...*/ }; - -// в IE8- false -// в остальных браузерах ошибка, т.к. имя factorial не видно -alert( f === factorial ); -``` - -Все остальные браузеры полностью поддерживают именованные функциональные выражения. -[/warn] - - -[smart header="Устаревшее специальное значение `arguments.callee`"] -Если вы давно работаете с JavaScript, то, возможно, знаете, что раньше для этой цели также служило специальное значение `arguments.callee`. - -Если это название вам ни о чём не говорит -- всё в порядке, читайте дальше, мы обязательно обсудим его [в отдельной главе](#arguments-callee). - -Если же вы в курсе, то стоит иметь в виду, что оно официально исключено из современного стандарта. А NFE -- это наше настоящее. -[/smart] - - -## Итого - -Если функция задана как Function Expression, ей можно дать имя. - -Оно будет доступно только внутри функции (кроме IE8-). - -Это имя предназначено для надёжного рекурсивного вызова функции, даже если она записана в другую переменную. - -Обратим внимание, что с Function Declaration так поступить нельзя. Такое "специальное" внутреннее имя функции задаётся только в синтаксисе Function Expression. - diff --git a/1-js/2-first-steps/22-javascript-specials/article.md b/1-js/2-first-steps/22-javascript-specials/article.md index 9e9fdea3..f9ccc903 100644 --- a/1-js/2-first-steps/22-javascript-specials/article.md +++ b/1-js/2-first-steps/22-javascript-specials/article.md @@ -1,4 +1,4 @@ -# Всё вместе: особенности JavaScript +# Всё вместе: особенности JavaScript TODO В этой главе приводятся основные особенности JavaScript, на уровне базовых конструкций, типов, синтаксиса. diff --git a/1-js/2-first-steps/3-structure/article.md b/1-js/2-first-steps/3-structure/article.md index 71b6e27b..e650bd67 100644 --- a/1-js/2-first-steps/3-structure/article.md +++ b/1-js/2-first-steps/3-structure/article.md @@ -65,24 +65,35 @@ For a curious reader who might be interested in a concrete example, check this c [1, 2].forEach(alert) ``` -It shows `1` then `2`. What `[...].forEach` means -- does not matter here (we'll get it later). Now let's insert an `alert` without a semicolon before it: +It shows `1` then `2`. + +Please don't think about the meaning of `[...].forEach` just for now -- it does not matter here (we'll get it later). + +Now let's prepend an `alert` *without a semicolon* before it: ```js //+ run no-beautify -alert( "Without a semicolon we get an error here" ) // printed -[1, 2].forEach(alert) // not printed +alert( "..." ) // works +[1, 2].forEach(alert) // doesn't work! ``` Now only the phrase is shown, not the numbers. And we can see an error in the developer console. -That's exactly because JavaScript engine did not insert a semicolon before square brackets `[...]` and misunderstood the code. - -Everything's fine if we add a semicolon: +But everything's fine if we add a semicolon: ```js //+ run alert( "With the semicolon everything works" ); // printed [1, 2].forEach(alert) // printed too ``` + +The error in the former variant occurs because JavaScript engine does not autoinsert a semicolon before square brackets `[...]`, so it was actually treated as a one-line statement: + +```js +//+ run no-beautify +// without semicolon after alert it becomes +alert( "..." )[1, 2].forEach(alert) // doesn't work! +``` + [/smart] As a conclusion, it's recommended to put semicolons between statements even if they are separated by newlines. This rule is widely adopted by the community. @@ -147,7 +158,7 @@ alert( 'World' ); ``` [/warn] -Don't hesitate to comment. They more code is in the project -- the more helpful good comments are. +Don't hesitate to comment. Comments increase the overall code footprint, but that's not a problem at all, because there are many tools which minify the code before publishing to production server and remove comments in the process. @@ -159,7 +170,8 @@ There are various types of comments, answering different questions:
  • Which counter-intuitive or implicit connections it has with other parts of the script?
  • -All these comments are highly valuable. + +Further in the tutorial we'll make more notes about how to write the code better, easier to read and maintain. We'll also talk more about comments. [smart header="The good code is inherently readable and self-commenting"] Please note that the first type of comments ("what the code does") should be used to describe a "high-level" action, like the overall architecture, a function or a chunk of code. It's purpose is to give an overview, so a reader doesn't need to delve into the code and figure out. @@ -167,5 +179,3 @@ Please note that the first type of comments ("what the code does") should be use Novice programmers sometimes tend to elaborate too much. Please don't. The good code is inherently readable. No need to describe what few lines do. Unless it's something hard to grasp, and *then* it's worth to consider rewriting the code at the first place rather than commenting it. [/smart] -Further in the tutorial we'll make more notes about how to write the code better, easier to read and maintain. - diff --git a/1-js/2-first-steps/5-variables/variable-change.png b/1-js/2-first-steps/5-variables/variable-change.png index 19fa6fbf..6e299520 100644 Binary files a/1-js/2-first-steps/5-variables/variable-change.png and b/1-js/2-first-steps/5-variables/variable-change.png differ diff --git a/1-js/2-first-steps/5-variables/variable-change@2x.png b/1-js/2-first-steps/5-variables/variable-change@2x.png index d00fbe15..926552cb 100644 Binary files a/1-js/2-first-steps/5-variables/variable-change@2x.png and b/1-js/2-first-steps/5-variables/variable-change@2x.png differ diff --git a/1-js/2-first-steps/5-variables/variable.png b/1-js/2-first-steps/5-variables/variable.png index aecd47ad..a8b84421 100644 Binary files a/1-js/2-first-steps/5-variables/variable.png and b/1-js/2-first-steps/5-variables/variable.png differ diff --git a/1-js/2-first-steps/5-variables/variable@2x.png b/1-js/2-first-steps/5-variables/variable@2x.png index 97d2b79d..10504e87 100644 Binary files a/1-js/2-first-steps/5-variables/variable@2x.png and b/1-js/2-first-steps/5-variables/variable@2x.png differ diff --git a/1-js/3-writing-js/1-debugging-chrome/article.md b/1-js/3-code-quality/1-debugging-chrome/article.md similarity index 99% rename from 1-js/3-writing-js/1-debugging-chrome/article.md rename to 1-js/3-code-quality/1-debugging-chrome/article.md index cce3064d..aa5b3fa0 100644 --- a/1-js/3-writing-js/1-debugging-chrome/article.md +++ b/1-js/3-code-quality/1-debugging-chrome/article.md @@ -1,4 +1,4 @@ -# Отладка в браузере Chrome +# TODO: Отладка в браузере Chrome Перед тем, как двигаться дальше, поговорим об отладке скриптов. diff --git a/1-js/3-writing-js/1-debugging-chrome/chrome_break_error.png b/1-js/3-code-quality/1-debugging-chrome/chrome_break_error.png similarity index 100% rename from 1-js/3-writing-js/1-debugging-chrome/chrome_break_error.png rename to 1-js/3-code-quality/1-debugging-chrome/chrome_break_error.png diff --git a/1-js/3-writing-js/1-debugging-chrome/chrome_break_error@2x.png b/1-js/3-code-quality/1-debugging-chrome/chrome_break_error@2x.png old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/1-debugging-chrome/chrome_break_error@2x.png rename to 1-js/3-code-quality/1-debugging-chrome/chrome_break_error@2x.png diff --git a/1-js/3-writing-js/1-debugging-chrome/chrome_sources.png b/1-js/3-code-quality/1-debugging-chrome/chrome_sources.png similarity index 100% rename from 1-js/3-writing-js/1-debugging-chrome/chrome_sources.png rename to 1-js/3-code-quality/1-debugging-chrome/chrome_sources.png diff --git a/1-js/3-writing-js/1-debugging-chrome/chrome_sources@2x.png b/1-js/3-code-quality/1-debugging-chrome/chrome_sources@2x.png old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/1-debugging-chrome/chrome_sources@2x.png rename to 1-js/3-code-quality/1-debugging-chrome/chrome_sources@2x.png diff --git a/1-js/3-writing-js/1-debugging-chrome/chrome_sources_break.png b/1-js/3-code-quality/1-debugging-chrome/chrome_sources_break.png similarity index 100% rename from 1-js/3-writing-js/1-debugging-chrome/chrome_sources_break.png rename to 1-js/3-code-quality/1-debugging-chrome/chrome_sources_break.png diff --git a/1-js/3-writing-js/1-debugging-chrome/chrome_sources_break@2x.png b/1-js/3-code-quality/1-debugging-chrome/chrome_sources_break@2x.png old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/1-debugging-chrome/chrome_sources_break@2x.png rename to 1-js/3-code-quality/1-debugging-chrome/chrome_sources_break@2x.png diff --git a/1-js/3-writing-js/1-debugging-chrome/chrome_sources_breakpoint.png b/1-js/3-code-quality/1-debugging-chrome/chrome_sources_breakpoint.png similarity index 100% rename from 1-js/3-writing-js/1-debugging-chrome/chrome_sources_breakpoint.png rename to 1-js/3-code-quality/1-debugging-chrome/chrome_sources_breakpoint.png diff --git a/1-js/3-writing-js/1-debugging-chrome/chrome_sources_breakpoint@2x.png b/1-js/3-code-quality/1-debugging-chrome/chrome_sources_breakpoint@2x.png old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/1-debugging-chrome/chrome_sources_breakpoint@2x.png rename to 1-js/3-code-quality/1-debugging-chrome/chrome_sources_breakpoint@2x.png diff --git a/1-js/3-writing-js/1-debugging-chrome/chrome_sources_buttons.png b/1-js/3-code-quality/1-debugging-chrome/chrome_sources_buttons.png similarity index 100% rename from 1-js/3-writing-js/1-debugging-chrome/chrome_sources_buttons.png rename to 1-js/3-code-quality/1-debugging-chrome/chrome_sources_buttons.png diff --git a/1-js/3-writing-js/1-debugging-chrome/chrome_sources_buttons@2x.png b/1-js/3-code-quality/1-debugging-chrome/chrome_sources_buttons@2x.png old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/1-debugging-chrome/chrome_sources_buttons@2x.png rename to 1-js/3-code-quality/1-debugging-chrome/chrome_sources_buttons@2x.png diff --git a/1-js/3-writing-js/1-debugging-chrome/console_error.png b/1-js/3-code-quality/1-debugging-chrome/console_error.png similarity index 100% rename from 1-js/3-writing-js/1-debugging-chrome/console_error.png rename to 1-js/3-code-quality/1-debugging-chrome/console_error.png diff --git a/1-js/3-writing-js/1-debugging-chrome/console_error@2x.png b/1-js/3-code-quality/1-debugging-chrome/console_error@2x.png old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/1-debugging-chrome/console_error@2x.png rename to 1-js/3-code-quality/1-debugging-chrome/console_error@2x.png diff --git a/1-js/3-writing-js/1-debugging-chrome/debugging.view/index.html b/1-js/3-code-quality/1-debugging-chrome/debugging.view/index.html old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/1-debugging-chrome/debugging.view/index.html rename to 1-js/3-code-quality/1-debugging-chrome/debugging.view/index.html diff --git a/1-js/3-writing-js/1-debugging-chrome/debugging.view/pow.js b/1-js/3-code-quality/1-debugging-chrome/debugging.view/pow.js old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/1-debugging-chrome/debugging.view/pow.js rename to 1-js/3-code-quality/1-debugging-chrome/debugging.view/pow.js diff --git a/1-js/3-writing-js/1-debugging-chrome/error.view/index.html b/1-js/3-code-quality/1-debugging-chrome/error.view/index.html old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/1-debugging-chrome/error.view/index.html rename to 1-js/3-code-quality/1-debugging-chrome/error.view/index.html diff --git a/1-js/3-writing-js/1-debugging-chrome/error.view/pow.js b/1-js/3-code-quality/1-debugging-chrome/error.view/pow.js old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/1-debugging-chrome/error.view/pow.js rename to 1-js/3-code-quality/1-debugging-chrome/error.view/pow.js diff --git a/1-js/3-writing-js/1-debugging-chrome/manage1.png b/1-js/3-code-quality/1-debugging-chrome/manage1.png similarity index 100% rename from 1-js/3-writing-js/1-debugging-chrome/manage1.png rename to 1-js/3-code-quality/1-debugging-chrome/manage1.png diff --git a/1-js/3-writing-js/1-debugging-chrome/manage1@2x.png b/1-js/3-code-quality/1-debugging-chrome/manage1@2x.png old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/1-debugging-chrome/manage1@2x.png rename to 1-js/3-code-quality/1-debugging-chrome/manage1@2x.png diff --git a/1-js/3-writing-js/1-debugging-chrome/manage2.png b/1-js/3-code-quality/1-debugging-chrome/manage2.png similarity index 100% rename from 1-js/3-writing-js/1-debugging-chrome/manage2.png rename to 1-js/3-code-quality/1-debugging-chrome/manage2.png diff --git a/1-js/3-writing-js/1-debugging-chrome/manage2@2x.png b/1-js/3-code-quality/1-debugging-chrome/manage2@2x.png old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/1-debugging-chrome/manage2@2x.png rename to 1-js/3-code-quality/1-debugging-chrome/manage2@2x.png diff --git a/1-js/3-writing-js/1-debugging-chrome/manage3.png b/1-js/3-code-quality/1-debugging-chrome/manage3.png similarity index 100% rename from 1-js/3-writing-js/1-debugging-chrome/manage3.png rename to 1-js/3-code-quality/1-debugging-chrome/manage3.png diff --git a/1-js/3-writing-js/1-debugging-chrome/manage3@2x.png b/1-js/3-code-quality/1-debugging-chrome/manage3@2x.png old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/1-debugging-chrome/manage3@2x.png rename to 1-js/3-code-quality/1-debugging-chrome/manage3@2x.png diff --git a/1-js/3-writing-js/1-debugging-chrome/manage4.png b/1-js/3-code-quality/1-debugging-chrome/manage4.png similarity index 100% rename from 1-js/3-writing-js/1-debugging-chrome/manage4.png rename to 1-js/3-code-quality/1-debugging-chrome/manage4.png diff --git a/1-js/3-writing-js/1-debugging-chrome/manage4@2x.png b/1-js/3-code-quality/1-debugging-chrome/manage4@2x.png old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/1-debugging-chrome/manage4@2x.png rename to 1-js/3-code-quality/1-debugging-chrome/manage4@2x.png diff --git a/1-js/3-writing-js/1-debugging-chrome/manage5.png b/1-js/3-code-quality/1-debugging-chrome/manage5.png similarity index 100% rename from 1-js/3-writing-js/1-debugging-chrome/manage5.png rename to 1-js/3-code-quality/1-debugging-chrome/manage5.png diff --git a/1-js/3-writing-js/1-debugging-chrome/manage5@2x.png b/1-js/3-code-quality/1-debugging-chrome/manage5@2x.png old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/1-debugging-chrome/manage5@2x.png rename to 1-js/3-code-quality/1-debugging-chrome/manage5@2x.png diff --git a/1-js/3-writing-js/1-debugging-chrome/manage6.png b/1-js/3-code-quality/1-debugging-chrome/manage6.png similarity index 100% rename from 1-js/3-writing-js/1-debugging-chrome/manage6.png rename to 1-js/3-code-quality/1-debugging-chrome/manage6.png diff --git a/1-js/3-writing-js/1-debugging-chrome/manage6@2x.png b/1-js/3-code-quality/1-debugging-chrome/manage6@2x.png old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/1-debugging-chrome/manage6@2x.png rename to 1-js/3-code-quality/1-debugging-chrome/manage6@2x.png diff --git a/1-js/3-writing-js/1-debugging-chrome/statusbarButtonGlyphs.svg b/1-js/3-code-quality/1-debugging-chrome/statusbarButtonGlyphs.svg similarity index 100% rename from 1-js/3-writing-js/1-debugging-chrome/statusbarButtonGlyphs.svg rename to 1-js/3-code-quality/1-debugging-chrome/statusbarButtonGlyphs.svg diff --git a/1-js/3-writing-js/3-write-unmain-code/article.md b/1-js/3-code-quality/3-write-unmain-code/article.md similarity index 100% rename from 1-js/3-writing-js/3-write-unmain-code/article.md rename to 1-js/3-code-quality/3-write-unmain-code/article.md diff --git a/1-js/3-writing-js/4-testing/1-pow-nan-spec/_js.view/solution.js b/1-js/3-code-quality/4-testing/1-pow-nan-spec/_js.view/solution.js similarity index 100% rename from 1-js/3-writing-js/4-testing/1-pow-nan-spec/_js.view/solution.js rename to 1-js/3-code-quality/4-testing/1-pow-nan-spec/_js.view/solution.js diff --git a/1-js/3-writing-js/4-testing/1-pow-nan-spec/_js.view/source.js b/1-js/3-code-quality/4-testing/1-pow-nan-spec/_js.view/source.js similarity index 100% rename from 1-js/3-writing-js/4-testing/1-pow-nan-spec/_js.view/source.js rename to 1-js/3-code-quality/4-testing/1-pow-nan-spec/_js.view/source.js diff --git a/1-js/3-writing-js/4-testing/1-pow-nan-spec/_js.view/test.js b/1-js/3-code-quality/4-testing/1-pow-nan-spec/_js.view/test.js similarity index 100% rename from 1-js/3-writing-js/4-testing/1-pow-nan-spec/_js.view/test.js rename to 1-js/3-code-quality/4-testing/1-pow-nan-spec/_js.view/test.js diff --git a/1-js/3-writing-js/4-testing/1-pow-nan-spec/solution.md b/1-js/3-code-quality/4-testing/1-pow-nan-spec/solution.md similarity index 100% rename from 1-js/3-writing-js/4-testing/1-pow-nan-spec/solution.md rename to 1-js/3-code-quality/4-testing/1-pow-nan-spec/solution.md diff --git a/1-js/3-writing-js/4-testing/1-pow-nan-spec/task.md b/1-js/3-code-quality/4-testing/1-pow-nan-spec/task.md similarity index 100% rename from 1-js/3-writing-js/4-testing/1-pow-nan-spec/task.md rename to 1-js/3-code-quality/4-testing/1-pow-nan-spec/task.md diff --git a/1-js/3-writing-js/4-testing/2-pow-test-0/solution.md b/1-js/3-code-quality/4-testing/2-pow-test-0/solution.md similarity index 100% rename from 1-js/3-writing-js/4-testing/2-pow-test-0/solution.md rename to 1-js/3-code-quality/4-testing/2-pow-test-0/solution.md diff --git a/1-js/3-writing-js/4-testing/2-pow-test-0/solution.view/index.html b/1-js/3-code-quality/4-testing/2-pow-test-0/solution.view/index.html similarity index 100% rename from 1-js/3-writing-js/4-testing/2-pow-test-0/solution.view/index.html rename to 1-js/3-code-quality/4-testing/2-pow-test-0/solution.view/index.html diff --git a/1-js/3-writing-js/4-testing/2-pow-test-0/solution.view/test.js b/1-js/3-code-quality/4-testing/2-pow-test-0/solution.view/test.js similarity index 100% rename from 1-js/3-writing-js/4-testing/2-pow-test-0/solution.view/test.js rename to 1-js/3-code-quality/4-testing/2-pow-test-0/solution.view/test.js diff --git a/1-js/3-writing-js/4-testing/2-pow-test-0/source.view/index.html b/1-js/3-code-quality/4-testing/2-pow-test-0/source.view/index.html similarity index 100% rename from 1-js/3-writing-js/4-testing/2-pow-test-0/source.view/index.html rename to 1-js/3-code-quality/4-testing/2-pow-test-0/source.view/index.html diff --git a/1-js/3-writing-js/4-testing/2-pow-test-0/source.view/test.js b/1-js/3-code-quality/4-testing/2-pow-test-0/source.view/test.js similarity index 100% rename from 1-js/3-writing-js/4-testing/2-pow-test-0/source.view/test.js rename to 1-js/3-code-quality/4-testing/2-pow-test-0/source.view/test.js diff --git a/1-js/3-writing-js/4-testing/2-pow-test-0/task.md b/1-js/3-code-quality/4-testing/2-pow-test-0/task.md similarity index 100% rename from 1-js/3-writing-js/4-testing/2-pow-test-0/task.md rename to 1-js/3-code-quality/4-testing/2-pow-test-0/task.md diff --git a/1-js/3-writing-js/4-testing/3-pow-test-wrong/solution.md b/1-js/3-code-quality/4-testing/3-pow-test-wrong/solution.md similarity index 100% rename from 1-js/3-writing-js/4-testing/3-pow-test-wrong/solution.md rename to 1-js/3-code-quality/4-testing/3-pow-test-wrong/solution.md diff --git a/1-js/3-writing-js/4-testing/3-pow-test-wrong/task.md b/1-js/3-code-quality/4-testing/3-pow-test-wrong/task.md similarity index 100% rename from 1-js/3-writing-js/4-testing/3-pow-test-wrong/task.md rename to 1-js/3-code-quality/4-testing/3-pow-test-wrong/task.md diff --git a/1-js/3-writing-js/4-testing/article.md b/1-js/3-code-quality/4-testing/article.md similarity index 100% rename from 1-js/3-writing-js/4-testing/article.md rename to 1-js/3-code-quality/4-testing/article.md diff --git a/1-js/3-writing-js/4-testing/beforeafter.view/index.html b/1-js/3-code-quality/4-testing/beforeafter.view/index.html old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/4-testing/beforeafter.view/index.html rename to 1-js/3-code-quality/4-testing/beforeafter.view/index.html diff --git a/1-js/3-writing-js/4-testing/beforeafter.view/test.js b/1-js/3-code-quality/4-testing/beforeafter.view/test.js old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/4-testing/beforeafter.view/test.js rename to 1-js/3-code-quality/4-testing/beforeafter.view/test.js diff --git a/1-js/3-writing-js/4-testing/index.html b/1-js/3-code-quality/4-testing/index.html old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/4-testing/index.html rename to 1-js/3-code-quality/4-testing/index.html diff --git a/1-js/3-writing-js/4-testing/pow-1.view/index.html b/1-js/3-code-quality/4-testing/pow-1.view/index.html old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/4-testing/pow-1.view/index.html rename to 1-js/3-code-quality/4-testing/pow-1.view/index.html diff --git a/1-js/3-writing-js/4-testing/pow-1.view/test.js b/1-js/3-code-quality/4-testing/pow-1.view/test.js old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/4-testing/pow-1.view/test.js rename to 1-js/3-code-quality/4-testing/pow-1.view/test.js diff --git a/1-js/3-writing-js/4-testing/pow-2.view/index.html b/1-js/3-code-quality/4-testing/pow-2.view/index.html old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/4-testing/pow-2.view/index.html rename to 1-js/3-code-quality/4-testing/pow-2.view/index.html diff --git a/1-js/3-writing-js/4-testing/pow-2.view/test.js b/1-js/3-code-quality/4-testing/pow-2.view/test.js old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/4-testing/pow-2.view/test.js rename to 1-js/3-code-quality/4-testing/pow-2.view/test.js diff --git a/1-js/3-writing-js/4-testing/pow-3.view/index.html b/1-js/3-code-quality/4-testing/pow-3.view/index.html old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/4-testing/pow-3.view/index.html rename to 1-js/3-code-quality/4-testing/pow-3.view/index.html diff --git a/1-js/3-writing-js/4-testing/pow-3.view/test.js b/1-js/3-code-quality/4-testing/pow-3.view/test.js old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/4-testing/pow-3.view/test.js rename to 1-js/3-code-quality/4-testing/pow-3.view/test.js diff --git a/1-js/3-writing-js/4-testing/pow-4.view/index.html b/1-js/3-code-quality/4-testing/pow-4.view/index.html old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/4-testing/pow-4.view/index.html rename to 1-js/3-code-quality/4-testing/pow-4.view/index.html diff --git a/1-js/3-writing-js/4-testing/pow-4.view/test.js b/1-js/3-code-quality/4-testing/pow-4.view/test.js old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/4-testing/pow-4.view/test.js rename to 1-js/3-code-quality/4-testing/pow-4.view/test.js diff --git a/1-js/3-writing-js/4-testing/pow-full.view/index.html b/1-js/3-code-quality/4-testing/pow-full.view/index.html old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/4-testing/pow-full.view/index.html rename to 1-js/3-code-quality/4-testing/pow-full.view/index.html diff --git a/1-js/3-writing-js/4-testing/pow-full.view/test.js b/1-js/3-code-quality/4-testing/pow-full.view/test.js old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/4-testing/pow-full.view/test.js rename to 1-js/3-code-quality/4-testing/pow-full.view/test.js diff --git a/1-js/3-writing-js/4-testing/pow-min.view/index.html b/1-js/3-code-quality/4-testing/pow-min.view/index.html old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/4-testing/pow-min.view/index.html rename to 1-js/3-code-quality/4-testing/pow-min.view/index.html diff --git a/1-js/3-writing-js/4-testing/pow-min.view/test.js b/1-js/3-code-quality/4-testing/pow-min.view/test.js old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/4-testing/pow-min.view/test.js rename to 1-js/3-code-quality/4-testing/pow-min.view/test.js diff --git a/1-js/3-writing-js/4-testing/pow-nan-assert.view/index.html b/1-js/3-code-quality/4-testing/pow-nan-assert.view/index.html old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/4-testing/pow-nan-assert.view/index.html rename to 1-js/3-code-quality/4-testing/pow-nan-assert.view/index.html diff --git a/1-js/3-writing-js/4-testing/pow-nan-assert.view/test.js b/1-js/3-code-quality/4-testing/pow-nan-assert.view/test.js old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/4-testing/pow-nan-assert.view/test.js rename to 1-js/3-code-quality/4-testing/pow-nan-assert.view/test.js diff --git a/1-js/3-writing-js/4-testing/pow-nan.view/index.html b/1-js/3-code-quality/4-testing/pow-nan.view/index.html old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/4-testing/pow-nan.view/index.html rename to 1-js/3-code-quality/4-testing/pow-nan.view/index.html diff --git a/1-js/3-writing-js/4-testing/pow-nan.view/test.js b/1-js/3-code-quality/4-testing/pow-nan.view/test.js old mode 100755 new mode 100644 similarity index 100% rename from 1-js/3-writing-js/4-testing/pow-nan.view/test.js rename to 1-js/3-code-quality/4-testing/pow-nan.view/test.js diff --git a/1-js/3-writing-js/index.md b/1-js/3-code-quality/index.md similarity index 100% rename from 1-js/3-writing-js/index.md rename to 1-js/3-code-quality/index.md diff --git a/1-js/3-writing-js/2-coding-style/code-style.png b/1-js/3-writing-js/2-coding-style/code-style.png deleted file mode 100644 index d41a9883..00000000 Binary files a/1-js/3-writing-js/2-coding-style/code-style.png and /dev/null differ diff --git a/1-js/3-writing-js/2-coding-style/code-style@2x.png b/1-js/3-writing-js/2-coding-style/code-style@2x.png deleted file mode 100644 index acb8ac1b..00000000 Binary files a/1-js/3-writing-js/2-coding-style/code-style@2x.png and /dev/null differ diff --git a/1-js/3-writing-js/2-coding-style/figure-bracket-style.png b/1-js/3-writing-js/2-coding-style/figure-bracket-style.png deleted file mode 100644 index 992d126e..00000000 Binary files a/1-js/3-writing-js/2-coding-style/figure-bracket-style.png and /dev/null differ diff --git a/1-js/3-writing-js/2-coding-style/figure-bracket-style@2x.png b/1-js/3-writing-js/2-coding-style/figure-bracket-style@2x.png deleted file mode 100644 index 7b937e88..00000000 Binary files a/1-js/3-writing-js/2-coding-style/figure-bracket-style@2x.png and /dev/null differ diff --git a/1-js/4-data-structures/4-object/object-person-1.png b/1-js/4-data-structures/4-object/object-person-1.png index 532330e0..2d16805f 100644 Binary files a/1-js/4-data-structures/4-object/object-person-1.png and b/1-js/4-data-structures/4-object/object-person-1.png differ diff --git a/1-js/4-data-structures/4-object/object-person-1@2x.png b/1-js/4-data-structures/4-object/object-person-1@2x.png index 7904d95c..9bb2f294 100644 Binary files a/1-js/4-data-structures/4-object/object-person-1@2x.png and b/1-js/4-data-structures/4-object/object-person-1@2x.png differ diff --git a/1-js/4-data-structures/4-object/object-person-2.png b/1-js/4-data-structures/4-object/object-person-2.png index 4630054b..bcf6509e 100644 Binary files a/1-js/4-data-structures/4-object/object-person-2.png and b/1-js/4-data-structures/4-object/object-person-2.png differ diff --git a/1-js/4-data-structures/4-object/object-person-2@2x.png b/1-js/4-data-structures/4-object/object-person-2@2x.png index 73ab98e8..82eaa0e6 100644 Binary files a/1-js/4-data-structures/4-object/object-person-2@2x.png and b/1-js/4-data-structures/4-object/object-person-2@2x.png differ diff --git a/1-js/4-data-structures/4-object/object-person-empty.png b/1-js/4-data-structures/4-object/object-person-empty.png index 668f13bf..364415e9 100644 Binary files a/1-js/4-data-structures/4-object/object-person-empty.png and b/1-js/4-data-structures/4-object/object-person-empty.png differ diff --git a/1-js/4-data-structures/4-object/object-person-empty@2x.png b/1-js/4-data-structures/4-object/object-person-empty@2x.png index da71618c..35ad328d 100644 Binary files a/1-js/4-data-structures/4-object/object-person-empty@2x.png and b/1-js/4-data-structures/4-object/object-person-empty@2x.png differ diff --git a/1-js/4-data-structures/4-object/object.png b/1-js/4-data-structures/4-object/object.png index abda01bb..e50f6446 100644 Binary files a/1-js/4-data-structures/4-object/object.png and b/1-js/4-data-structures/4-object/object.png differ diff --git a/1-js/4-data-structures/4-object/object@2x.png b/1-js/4-data-structures/4-object/object@2x.png index bd2590bb..09349f8c 100644 Binary files a/1-js/4-data-structures/4-object/object@2x.png and b/1-js/4-data-structures/4-object/object@2x.png differ diff --git a/1-js/4-data-structures/6-object-reference/variable-contains-reference.png b/1-js/4-data-structures/6-object-reference/variable-contains-reference.png index 53d18fed..92174cc2 100644 Binary files a/1-js/4-data-structures/6-object-reference/variable-contains-reference.png and b/1-js/4-data-structures/6-object-reference/variable-contains-reference.png differ diff --git a/1-js/4-data-structures/6-object-reference/variable-contains-reference@2x.png b/1-js/4-data-structures/6-object-reference/variable-contains-reference@2x.png index 9a152357..cd19c4d2 100644 Binary files a/1-js/4-data-structures/6-object-reference/variable-contains-reference@2x.png and b/1-js/4-data-structures/6-object-reference/variable-contains-reference@2x.png differ diff --git a/1-js/4-data-structures/6-object-reference/variable-copy-reference.png b/1-js/4-data-structures/6-object-reference/variable-copy-reference.png index b6a502c3..03140b06 100644 Binary files a/1-js/4-data-structures/6-object-reference/variable-copy-reference.png and b/1-js/4-data-structures/6-object-reference/variable-copy-reference.png differ diff --git a/1-js/4-data-structures/6-object-reference/variable-copy-reference@2x.png b/1-js/4-data-structures/6-object-reference/variable-copy-reference@2x.png index 8e27b051..240cde67 100644 Binary files a/1-js/4-data-structures/6-object-reference/variable-copy-reference@2x.png and b/1-js/4-data-structures/6-object-reference/variable-copy-reference@2x.png differ diff --git a/1-js/4-data-structures/6-object-reference/variable-copy-value.png b/1-js/4-data-structures/6-object-reference/variable-copy-value.png index 33578c15..47c04035 100644 Binary files a/1-js/4-data-structures/6-object-reference/variable-copy-value.png and b/1-js/4-data-structures/6-object-reference/variable-copy-value.png differ diff --git a/1-js/4-data-structures/6-object-reference/variable-copy-value@2x.png b/1-js/4-data-structures/6-object-reference/variable-copy-value@2x.png index 588762f5..51d59493 100644 Binary files a/1-js/4-data-structures/6-object-reference/variable-copy-value@2x.png and b/1-js/4-data-structures/6-object-reference/variable-copy-value@2x.png differ diff --git a/1-js/4-data-structures/7-array/array-pop.png b/1-js/4-data-structures/7-array/array-pop.png index 672d87a9..af71f21b 100644 Binary files a/1-js/4-data-structures/7-array/array-pop.png and b/1-js/4-data-structures/7-array/array-pop.png differ diff --git a/1-js/4-data-structures/7-array/array-pop@2x.png b/1-js/4-data-structures/7-array/array-pop@2x.png index 0fd34a87..46b7ac2e 100644 Binary files a/1-js/4-data-structures/7-array/array-pop@2x.png and b/1-js/4-data-structures/7-array/array-pop@2x.png differ diff --git a/1-js/4-data-structures/7-array/array-shift.png b/1-js/4-data-structures/7-array/array-shift.png index 2236d731..a1df4bde 100644 Binary files a/1-js/4-data-structures/7-array/array-shift.png and b/1-js/4-data-structures/7-array/array-shift.png differ diff --git a/1-js/4-data-structures/7-array/array-shift@2x.png b/1-js/4-data-structures/7-array/array-shift@2x.png index 5e36dda7..c543119a 100644 Binary files a/1-js/4-data-structures/7-array/array-shift@2x.png and b/1-js/4-data-structures/7-array/array-shift@2x.png differ diff --git a/1-js/4-data-structures/7-array/array-speed.png b/1-js/4-data-structures/7-array/array-speed.png index fee6b518..d08f9c36 100644 Binary files a/1-js/4-data-structures/7-array/array-speed.png and b/1-js/4-data-structures/7-array/array-speed.png differ diff --git a/1-js/4-data-structures/7-array/array-speed@2x.png b/1-js/4-data-structures/7-array/array-speed@2x.png index 4419e1cd..dc678773 100644 Binary files a/1-js/4-data-structures/7-array/array-speed@2x.png and b/1-js/4-data-structures/7-array/array-speed@2x.png differ diff --git a/1-js/4-data-structures/7-array/queue.png b/1-js/4-data-structures/7-array/queue.png index 8a90ef30..ace82552 100644 Binary files a/1-js/4-data-structures/7-array/queue.png and b/1-js/4-data-structures/7-array/queue.png differ diff --git a/1-js/4-data-structures/7-array/queue@2x.png b/1-js/4-data-structures/7-array/queue@2x.png index 2a1281d0..8c221406 100644 Binary files a/1-js/4-data-structures/7-array/queue@2x.png and b/1-js/4-data-structures/7-array/queue@2x.png differ diff --git a/1-js/4-data-structures/7-array/stack.png b/1-js/4-data-structures/7-array/stack.png index 566da719..ba16ec0b 100644 Binary files a/1-js/4-data-structures/7-array/stack.png and b/1-js/4-data-structures/7-array/stack.png differ diff --git a/1-js/4-data-structures/7-array/stack@2x.png b/1-js/4-data-structures/7-array/stack@2x.png index 9301457d..86e41be9 100644 Binary files a/1-js/4-data-structures/7-array/stack@2x.png and b/1-js/4-data-structures/7-array/stack@2x.png differ diff --git a/1-js/4-data-structures/8-array-methods/9-output-single-linked-list/linked-list.png b/1-js/4-data-structures/8-array-methods/9-output-single-linked-list/linked-list.png index 0e714094..19835d1b 100644 Binary files a/1-js/4-data-structures/8-array-methods/9-output-single-linked-list/linked-list.png and b/1-js/4-data-structures/8-array-methods/9-output-single-linked-list/linked-list.png differ diff --git a/1-js/4-data-structures/8-array-methods/9-output-single-linked-list/linked-list@2x.png b/1-js/4-data-structures/8-array-methods/9-output-single-linked-list/linked-list@2x.png index feeefb72..563faff5 100644 Binary files a/1-js/4-data-structures/8-array-methods/9-output-single-linked-list/linked-list@2x.png and b/1-js/4-data-structures/8-array-methods/9-output-single-linked-list/linked-list@2x.png differ diff --git a/1-js/4-data-structures/9-array-iteration/reduce.png b/1-js/4-data-structures/9-array-iteration/reduce.png index 5ca1b5a0..f4caf0e6 100644 Binary files a/1-js/4-data-structures/9-array-iteration/reduce.png and b/1-js/4-data-structures/9-array-iteration/reduce.png differ diff --git a/1-js/4-data-structures/9-array-iteration/reduce@2x.png b/1-js/4-data-structures/9-array-iteration/reduce@2x.png index 0140b5d2..3424c8c4 100644 Binary files a/1-js/4-data-structures/9-array-iteration/reduce@2x.png and b/1-js/4-data-structures/9-array-iteration/reduce@2x.png differ diff --git a/archive/nfe.md b/archive/nfe.md new file mode 100644 index 00000000..7f7e2044 --- /dev/null +++ b/archive/nfe.md @@ -0,0 +1,140 @@ + +## Named Function Expression + +Named Function Expression or, shortly, NFE, is a term a Function Expression that has a name. + +For instance, let's take an ordinary Function Expression: + +```js +let sayHi = function(who) { + alert(`Hello, ${who}`); +}; +``` + +...And add a name to it: + +```js +let sayHi = function *!*func*/!*(who) { + alert(`Hello, ${who}`); +}; +``` + +What's the role of that additional `"func"` name? + +First let's note, that we're still having a Function Expression. Adding the name `"func"` after `function` did not make it a Function Declaration, because it is still created as a part of an assignment expression. + +Adding such a name also did not break anything. + +The function is still available as `sayHi()`: + +```js +//+ run +let sayHi = function *!*func*/!*(who) { + alert(`Hello, ${who}`); +}; + +sayHi("John"); // Hello, John +``` + +There are two special things about the name `func`: +
      +
    1. It allows to reference the function from inside itself.
    2. +
    3. It is not visible outside of the function.
    4. +
    + +For instance, the function `sayHi` below re-calls itself with `"Guest"` if no `who` is provided: + +```js +//+ run +let sayHi = function *!*func*/!*(who) { + if (who) { + alert(`Hello, ${who}`); + } else { +*!* + func("Guest"); // use func to re-call itself +*/!* + } +}; + +sayHi(); // Hello, Guest + +// But this won't work: +func(); // Error, func is not defined (not visible outside of the function) +``` + +Later we'll see more cases when a function wants to re-call itself with modified parameters. + +So, why won't we use `sayHi` for the nested call? + +Actually, in most cases we can: + +```js +let sayHi = function(who) { + if (who) { + alert(`Hello, ${who}`); + } else { +*!* + sayHi("Guest"); +*/!* + } +}; +``` + +The problem with the latter code is that the value of `sayHi` may change. The function may go to another variable: + +```js +//+ run +let sayHi = function *!*func*/!*(who) { + if (who) { + alert(`Hello, ${who}`); + } else { +*!* + func("Guest"); // (*) +*/!* + } +}; + +let welcome = sayHi; +sayHi = null; + +welcome(); // Hello, Guest (still works under different name) +``` + +Using `func` in the line `(*)` *guarantees* that this exactly function will be called. Using `sayHi` there + + +...But the name `func` is not visible outside of the function: + +```js +//+ run +let sayHi = function *!*func*/!*(who) { + // ... +}; + +*!* +func(); // Error: func is not defined +*/!* +``` + +Named Function Expressions are used in rare cases when: + + +The code below demonstrates both conditions: + +```js +//+ run +let sayHi = function *!*func*/!*(name) { + if (name) { + alert(`Hello, ${name}!`) + } else { + func("Guest"); + } +}; + +welcome(); // Works +``` + + diff --git a/archive/nfe_more.md b/archive/nfe_more.md new file mode 100644 index 00000000..b8e642cb --- /dev/null +++ b/archive/nfe_more.md @@ -0,0 +1,52 @@ + +Let's output it using `alert`: + +```js +//+ run +function sayHi() { + alert( "Hello" ); +} + +*!* +alert( sayHi ); // shows the function code +*/!* +``` + +Note that there are no brackets after `sayHi` in the last line. The function is not called there. + +The code above only shows the string representation of the function, that is it's source code. + +[cut] + + +As the function is a value, we can copy it to another variable: + +```js +//+ run no-beautify +function sayHi() { // (1) + alert( "Hello" ); +} + +let func = sayHi; // (2) +func(); // Hello // (3) + +sayHi = null; // (4) +sayHi(); // error +``` + +
      +
    1. Function declaration `(1)` creates the function and puts it into the variable `sayHi`"
    2. +
    3. Line `(2)` copies it into variable `func`. + +Please note again: there are no brackets after `sayHi`. If they were, then the call `let func = sayHi()` would write a *result* of `sayHi()` into `func`, not the function itself.
    4. +
    5. At the moment `(3)` the function can be called both as `sayHi()` and `func()`.
    6. +
    7. ...We can overwrite `sayHi` easily. As well as `func`, they are normal variables. Naturally, the call attempt would fail in the case `(4)`.
    8. +
    + +[smart header="A function is an \"action value\""] +Regular values like strings or numbers represent the *data*. + +A function can be perceived as an *action*. + +A function declaration creates that action and puts it into a variable of the given name. Then we can run it via brackets `()` or copy into another variable. +[/smart] diff --git a/1-js/2-first-steps/20-recursion/article.md b/archive/recursion.md similarity index 85% rename from 1-js/2-first-steps/20-recursion/article.md rename to archive/recursion.md index 567fe119..0af749b5 100644 --- a/1-js/2-first-steps/20-recursion/article.md +++ b/archive/recursion.md @@ -1,19 +1,60 @@ -# Рекурсия, стек +# Recursion, stack -В коде функции могут вызывать другие функции для выполнения подзадач. +It's ok for a function to rely on other functions for sub-tasks. -Частный случай подвызова -- когда функция вызывает сама себя. Это называется *рекурсией*. +We've already been using it when `welcome()` relied on `alert()` call to show the message. -Рекурсия используется для ситуаций, когда выполнение одной сложной задачи можно представить как некое действие в совокупности с решением той же задачи в более простом варианте. +In particular, a function can make a sub-call *itself*. That's called *a recursion*. -Сейчас мы посмотрим примеры. - -Рекурсия -- общая тема программирования, не относящаяся напрямую к JavaScript. Если вы разрабатывали на других языках или изучали программирование раньше в ВУЗе, то наверняка уже знаете, что это такое. - -Эта глава предназначена для читателей, которые пока с этой темой незнакомы и хотят лучше разобраться в том, как работают функции. +We'll fiddle around that advanced case to better learn how functions work. [cut] +[smart header="A topic you already know?"] +Recursion is a general programming term. If you are already familiar with it, then you may list the page to the next chapter. Please read on if you are new to functions or just prefer not to skip parts. +[/smart] + +## Divide and conquer + +Divide and conquer (or "divide and rule") is an ancient strategy attributed to Philip II of Macedon and mentioned by the Roman emperor Julius Caesar, the French emperor Napolen and many other leaders. + +They used it to rule, but the similar thing is often done in programming. If we have a complex task, that we're not sure how to solve as a whole, then maybe we can split it and try to solve the smaller parts. + +And if smaller parts are still too big, then let's cut them and try to solve even smaller parts. + +Repeat the cutting until the parts are so small that it's obvious how to deal with them. + +Sounds good? Now let's explore a case of this approach. + +## Eating an elephant + +Let's say we have a task "to eat an elephant". But how? + +The well-known humorous solution is: "piece by piece". We cut a piece, eat it and repeat the process. Sooner or later, the elephant is eaten. + +The algorithm can be reflected in the code: + +``` +function eat(elephant) { + cut a piece from the elephant + eat it + if (something left) { +*!* + eat(what's left of the elephant) // (*) +*/!* + } +} +``` + +The recursion occurs at line `(*)`: function `eat` after making things simpler passes the remaining data again to itself. + +Of course that's only one variant. For example, we could cut the elephant in 2 halves, then cut the halves in half again etc, until the parts are small enough to eat. Then put them into plates and pass to the guests. + +The core idea is the same: splitting the problem into multiple subproblems and doing the same with them if they're still big. + +## A power of a number + + ## Степень pow(x, n) через рекурсию @@ -241,3 +282,4 @@ function pow(x, n) { } [/head] + diff --git a/figures.sketch b/figures.sketch index 77fece17..aad178a9 100644 Binary files a/figures.sketch and b/figures.sketch differ