diff --git a/1-js/2-first-steps/02-structure/article.md b/1-js/2-first-steps/02-structure/article.md index 90d8cbad..7e6faa42 100644 --- a/1-js/2-first-steps/02-structure/article.md +++ b/1-js/2-first-steps/02-structure/article.md @@ -6,7 +6,7 @@ The first overall thing to know is the code structure. ## Statements -[Statements](https://en.wikipedia.org/wiki/Statement_(computer_science)) are syntax constructs and commands to perform actions. +Statements are syntax constructs and commands that perform actions. We've already seen a statement `alert('Hello, world!')`, which shows the message. @@ -48,11 +48,11 @@ alert(3 + + 2); ``` -The code outputs `6`, because JavaScript does not insert semicolons here. It is intuitively obvious that if the line ends with a plus `"+"`, then it is an "incomplete expression". And in this case that's actually fine and comfortable. +The code outputs `6`, because JavaScript does not insert semicolons here. It is intuitively obvious that if the line ends with a plus `"+"`, then it is an "incomplete expression", no semicolon required. And in this case that works as intended. **But there are situations where JavaScript "fails" to assume a semicolon where it is really needed.** -Errors which come appear in such cases are quite hard to find and fix. +Errors which occur in such cases are quite hard to find and fix. ````smart header="An example of the error" If you're curious to see a concrete example, check this code out: @@ -65,25 +65,29 @@ It shows `1` then `2`. No need to think about the meaning of the brackets `[]` and `forEach`, for now -- it does not matter. Let's just remember the result. -Now we prepend the code with an `alert` statement *not followed by a semicolon*: +Now let's put an `alert` before the code. And *not* finish it with a semicolon: ```js run no-beautify alert( "There will be an error" ) // shown -[1, 2].forEach(alert) // doesn't work! + +[1, 2].forEach(alert) // doesn't work any more! ``` Now if we run it, only the first `alert` is shown, and then an error. -But everything's fine if we add a semicolon: +But everything is fine again if we add a semicolon after `alert`: ```js run alert( "All fine now" ); // shown + [1, 2].forEach(alert) // this works too ``` -The error in the no-semicolon variant occurs because JavaScript engine does not assume a semicolon before square brackets `[...]`, so the code is actually treated as a one-line statement: +The error in the no-semicolon variant occurs because automatic semicolon insertion rules are complex, and in particular, JavaScript does not imply a semicolon before square brackets `[...]`. + +And, because the semicolon is not auto-inserted, the code is treated as a single statement, like this: ```js run no-beautify -alert( "There will be an error" )[1, 2].forEach(alert) +alert( "There will be an error" )[1, 2].forEach(alert) ``` And in this particular case, that's just wrong, hence the error. There are other situations when such thing happens. @@ -133,11 +137,11 @@ alert( 'World' ); ``` ```smart header="Use hotkeys!" -In most editors a line of code can be commented out by `key:Ctrl+/` hotkey for a single-line comment and something like `key:Ctrl+Shift+/` -- for multiline comments (select a code and press the hotkey). +In most editors a line of code can be commented out by `key:Ctrl+/` hotkey for a single-line comment and something like `key:Ctrl+Shift+/` -- for multiline comments (select a code and press the hotkey). For Mac try `key:Cmd` instead of `key:Ctrl`. ``` ````warn header="Nested comments are not supported!" -There may not be comments inside comments. +There may not be `/*...*/` inside another `/*...*/`. This code will die with an error: @@ -155,3 +159,4 @@ Comments increase the overall code footprint, but that's not a problem at all. T Further in the tutorial we'll devote a special chapter to code style, also explaining how to write better comments. +[todo is there such a chapter?] diff --git a/1-js/2-first-steps/03-strict-mode/article.md b/1-js/2-first-steps/03-strict-mode/article.md index b194e88e..41fdf9a3 100644 --- a/1-js/2-first-steps/03-strict-mode/article.md +++ b/1-js/2-first-steps/03-strict-mode/article.md @@ -48,9 +48,9 @@ Only comments may appear above `"use strict"`. ```smart header="`use strict` for functions" -We will learn functions (a way to group commands) soon. +We will learn functions (a way to group commands) soon. -Looking ahead let's just note that `"use strict"` can be put at the start of a function instead of the whole script. Then the strict mode is enabled in that function only. But usually people put it on top of scripts. +Looking ahead let's just note that `"use strict"` can be put at the start of a function (most kinds of functions) instead of the whole script. Then strict mode is enabled in that function only. But usually people use it for the whole script. ``` @@ -66,5 +66,6 @@ Here in the tutorial all code (except where said otherwise) works in `"use stric ## Summary - The `"use strict"` directive switches the engine to the "modern" mode, changing the behavior of some builtin features. -- Several modern features of the language enable `"use strict"` implicitly. -- It's recommended to start scripts with `"use strict"`. +- Several modern features of the language enable `"use strict"` implicitly, so it's quite hard to evade it. + +It's always recommended to start scripts with `"use strict"`. All examples in this book assume so, unless (very rarely) specified otherwise. diff --git a/1-js/2-first-steps/04-variables/article.md b/1-js/2-first-steps/04-variables/article.md index 3c1a32cb..5d8869a1 100644 --- a/1-js/2-first-steps/04-variables/article.md +++ b/1-js/2-first-steps/04-variables/article.md @@ -46,7 +46,7 @@ To be concise we can merge the variable declaration and assignment into a single ```js run let message = 'Hello!'; // define the variable and assign the value -alert( message ); // Hello! +alert(message); // Hello! ``` We can also declare multiple variables in one line: @@ -55,11 +55,11 @@ We can also declare multiple variables in one line: let user = 'John', age = 25, message = 'Hello'; ``` -That might seem shorter, but it's not recommended. For the sake of beter readability, please use a single line per variable. +That might seem shorter, but it's not recommended. For the sake of better readability, please use a single line per variable. -The rewritten code is a bit longer, but easier to read: +The multiline variant is a bit longer, but easier to read: -```js no-beautify +```js let user = 'John'; let age = 25; let message = 'Hello'; @@ -80,7 +80,7 @@ let user = 'John' , message = 'Hello'; ``` -Technically, all these variants do the same. So, it's a matter of personal taste and aestetics. +Technically, all these variants do the same. So, it's a matter of personal taste and aesthetics. ````smart header="`var` instead of `let`" @@ -103,7 +103,7 @@ For instance, the variable `message` can be imagined as a box labelled `"message ![](variable.png) -We can put any value into the box. +We can put any value into the box. Also we can change it. The value can be changed as many times as needed: @@ -211,12 +211,12 @@ let return = 5; // also can't name it "return", error! ````warn header="An assignment without `use strict`" -Normally, we need to define a variable before using it. But in the old times, it was technically possible to create a variable by a mere assignment of the value. This still works now in if we don't put `use strict`, the behavior is kept for compatibility with old scripts. +Normally, we need to define a variable before using it. But in the old times, it was technically possible to create a variable by a mere assignment of the value. This still works now in if we don't put `use strict`, the behavior is kept for compatibility with old scripts. ```js run no-strict num = 5; // the variable "num" is created if didn't exist -alert(num); // 5 +alert(num); // 5 ``` That's a bad practice of course, it gives an error in the strict mode: @@ -252,7 +252,7 @@ When a programmer is sure that the variable should never change, he can use `con ### Uppercase constants -There is a widespread practice to use constants as aliases for difficult-to-remember values that are known prior to execution. +There is a widespread practice to use constants as aliases for difficult-to-remember values that are known prior to execution. Such constants are named using capitals and underscores. @@ -269,19 +269,29 @@ let color = COLOR_ORANGE; alert( color ); // #FF7F00 ``` -`COLOR_ORANGE` is much easier to remember than `"#FF7F00"`. Also it is much easier to mistype in `"#FF7F00"` than in `COLOR_ORANGE`. And when reading the code -- `COLOR_ORANGE` is much more meaningful. +`COLOR_ORANGE` is much easier to remember than `"#FF7F00"`. Also it is much easier to mistype in `"#FF7F00"` than in `COLOR_ORANGE`. And when reading the code -- `COLOR_ORANGE` is much more meaningful. + +When should we use capitals for a constant, and when -- name them normally? Let's make that clear. + +Being a "constant" just means that the value never changes. But there are constants that are known prior to execution (like a hexadimal value for red), and there are those that are *calculated* during the execution, but do not change since then. + +```js +const ordinaryConst = /* an expression that uses the current date */; +// the expression value is not known prior to execution +// such a constant must be named normally +``` + +In other words, capital-named constants are only used as aliases for "hard-coded" values. ## Name things right -Talking about variables, there's an exteremely important thing. +Talking about variables, there's one more exteremely important thing. Please name the variables sensibly. Variable naming is one of the most important and complex skills in programming. A quick glance at variable names can obviously show which code is written by a beginner and which by an experienced guru. -In a real project, most of the time is spent on modifying and extending the existing code, rather than writing something completely new. - -And when we return to the code after some time of doing something else, it's much easier to find the information that is well-labelled. Or, in other words, when the variables are named right. +In a real project, most of the time is spent on modifying and extending the existing code base, rather than writing something completely separate of it. And when we return to the code after some time of doing something else, it's much easier to find the information that is well-labelled. Or, in other words, when the variables have good names. Please spend some time thinking about the right name for a variable before declaring it. That will repay you a lot. @@ -290,7 +300,7 @@ Few good-to-follow rules are: - Use human-readable names like `userName` or `shoppingCart`. - Stay away from abbreviations or short names `a`, `b`, `c`, unless you really know what you're doing. - Make the name maximally descriptive and concise. Examples of bad names are `data` and `value`. Such a name says nothing. It is only ok to use them if it's exceptionally obvious from the context which data or value is meant. -- Agree on terms within the team and in your own mind. If a site visitor is called a "user" then we should name variables like `currentUser` or `newUser`, but not `currentVisitor` or a `newManInTown`. +- Agree on terms within the team and in your own mind. If a site visitor is called a "user" then we should name related variables like `currentUser` or `newUser`, but not `currentVisitor` or a `newManInTown`. Sounds simple? Indeed it is. But creating good descriptive-and-concise names in practice is not. Go for it. @@ -301,7 +311,7 @@ As the result, the variable is like a box where people throw different things wi Such a programmer saves a little bit on variable declaration, but looses ten times more on debugging the code. -An extra variable is good, not evil. +An extra variable is good, not evil. Modern JavaScript minifiers and browsers optimize code well enough, so it won't create performance issues. Using different variables for values of different types can even help the engine to optimize better. ``` @@ -314,4 +324,4 @@ We can declare variables to store data. That can be done using `var` or `let` or - `var` -- is an old-school variable declaration. We'll study the subtle differences from `let` later. - `const` -- is like `let`, but the variable can't be changed. -Variables should be named in a way that allows to easily understand what's inside. \ No newline at end of file +Variables should be named in a way that allows to easily understand what's inside. diff --git a/1-js/2-first-steps/05-types/article.md b/1-js/2-first-steps/05-types/article.md index 7d9cef29..ce9edc09 100644 --- a/1-js/2-first-steps/05-types/article.md +++ b/1-js/2-first-steps/05-types/article.md @@ -1,8 +1,16 @@ # Data types -There are 7 data types in JavaScript. +A variable in JavaScript can contain any data. A variable can at one moment be a string and later recieve a numeric value: -In this chapter we'll get the common understanding of them. In further chapters we'll talk about each type in detail. +```js +// no error +let message = "hello"; +message = 123456; +``` + +Such languages are called "dynamically typed", meaning that there are language types, but variables are not bound to any of them. + +There are 7 basic data types in JavaScript. Here we'll study the basics, and in the next chapters we'll talk about each of them in detail. [cut] @@ -19,7 +27,7 @@ There are many operations for numbers, e.g. multiplication `*`, division `/`, ad Besides regular numbers there are so-called "special numeric values" which also belong to that type: `Infinity`, `-Infinity` and `NaN`. -- `Infinity` represents the mathematical [Infinity](https://en.wikipedia.org/wiki/Infinity). It is a value that's greater than any number. +- `Infinity` represents the mathematical [Infinity](https://en.wikipedia.org/wiki/Infinity) ∞. It is a special value that's greater than any number. We can get it as a result of division by zero: @@ -44,12 +52,12 @@ Besides regular numbers there are so-called "special numeric values" which also alert( "not a number" / 2 + 5 ); // NaN + 5 is still NaN ``` - So, in a long mathematical expression if we have `NaN` in one place, it propagates to the whole result. + So, if there's `NaN` somewhere in a mathematical expression, it propagates to the whole result. ```smart header="Mathematical operations are safe" -Doing maths is safe in JavaScript. We can do anything: divide by zero, treat non-numeric strings as numbers, etc. +Doing maths is safe in JavaScript. We can do anything: divide by zero, treat non-numeric strings as numbers, etc. -The script will never stop with a fatal error ("die"). At worst we'll get `NaN` as the result. +The script will never stop with a fatal error ("die"). At worst we'll get `NaN` as the result. ``` Special numeric values formally belong to the "number" type. Of course they are not numbers in a common sense of this word. @@ -80,7 +88,7 @@ let name = "John"; // embed variable alert( `Hello, ${name}!` ); // Hello, John! -// embed expression +// embed expression alert( `the result is ${1 + 2}` ); // the result is 3 ``` @@ -98,24 +106,24 @@ In JavaScript, there is no such type. There's only one type: `string`. A string The boolean type has only two values: `true` and `false`. -This type is commonly used to store yes/no values. +This type is commonly used to store yes/no values: `true` means "yes, correct", and `false` means the "no, incorrect". For instance: -```js no-beautify -let checked = true; // the form field is checked -checked = false; // the form field is not checked +```js +let checked1 = true; // yes, the form field is checked +let checked2 = false; // no, the form field is not checked ``` Boolean values also come as the result of comparisons: ```js run -let isGreater = 4 > 1; +let isGreater = 4 > 1; alert( isGreater ); // true (the comparison result is "yes") ``` -We'll cover booleans more deeply while discussing logical operators. +We'll cover booleans more deeply later while discussing [logical operators](/logical-ops). ## The "null" value @@ -131,13 +139,13 @@ In JavaScript `null` is not a "reference to a non-existing object" or a "null po It's just a special value which has the sense of "nothing", "empty" or "value unknown". -The code above states that the `age` is unknown or empty for some reason. +The code above states that the `age` is unknown or empty for some reason. ## The "undefined" value The special value `undefined` stands apart. It makes a type of its own, just like `null`. -The sense of `undefined` is "value is not assigned". +The sense of `undefined` is "value is not assigned". If a variable is declared, but not assigned, then its value is exactly `undefined`: @@ -163,15 +171,11 @@ alert( x ); // "undefined" The `object` type is special. -All other types are called "primitive", because their values can contain only a single thing (be it a string or a number or whatever). - -In contrast, objects are used to store collections data and more complex entities. We'll deal with them later after we know enough about primitives. - -The `symbol` type is used to create unique identifiers, mainly used to store data in objects. We'll return to them as soon as we cover objects. +All other types are called "primitive", because their values can contain only a single thing (be it a string or a number or whatever). In contrast, objects are used to store collections data and more complex entities. We'll deal with them later after we know enough about primitives. +The `symbol` type is used to create unique identifiers for objects. We have to mention it here for completeness, but we'd better study them after covering objects. [todo when ? chapter?] -[todo move tasks] ## The typeof operator [#type-typeof] [todo we need typeof in types] @@ -213,7 +217,7 @@ typeof alert // "function" (3) The last three lines may be a little unobvious so here's explanations: -1. `Math` is a built-in object that provides mathematical operations. We will learn it in the chapter . Here it servers as an example, nothing more. +1. `Math` is a built-in object that provides mathematical operations. We will learn it in the chapter . Here it serves just as an example of an object. 2. The result of `typeof null` equals to `"object"`. That's wrong. It is an officially recognized error in `typeof`, kept for compatibility. Of course, `null` is not an object. It is a special value with a separate type of its own. So, again, that's an error in the language. 3. The result of `typeof alert` is `"function"`, because `alert` is a function of the language. We'll study functions in the near future and see that actually functions belong to the object type. But `typeof` treats them differently. That's very convenient in practice. @@ -230,13 +234,10 @@ There are 7 basic types in JavaScript. - `object` for more complex data structures. - `symbol` for unique identifiers. -The `typeof` operator allows to see which type is stored in the variable. +The `typeof` operator allows to see which type is stored in the variable. - Two forms: `typeof x` or `typeof(x)`. - Returns a string with the name of the type, like `"string"`. - Mistreats `null` as an `object` -- the old official error in the language. In nearest chapters we'll concentrate on understanding how to operate on primitives and once we're familiar with that, then we'll move on to objects. - - - diff --git a/1-js/2-first-steps/06-type-conversions/article.md b/1-js/2-first-steps/06-type-conversions/article.md index 7d6db4db..a0d923d9 100644 --- a/1-js/2-first-steps/06-type-conversions/article.md +++ b/1-js/2-first-steps/06-type-conversions/article.md @@ -1,24 +1,18 @@ # Type Conversions -A variable in JavaScript can contain any data. A variable can at one moment be a string and later recieve a numeric value: +Most of time, operators and functions automatically convert a value to the right type. That's called "type coercion". -```js -// no error -let message = "hello"; -message = 123456; -``` +For example, `alert` automatically converts any value to a string, to show it. Or mathematical operations convert values to numbers. -...But some operations implicitly convert a value from one type to another. For example, `alert` automatically converts any value to a string, to show it. Or mathematical operations convert values to numbers. That is called *type coercion*. - -There are also cases when we need to explicitly convert between types to ensure that we store the right data the right way or to use special features of a certain type. +There are also cases when we need to explicitly convert a value to put things right. [cut] -```smart header="No objects here" -In this chapter we don't cover objects yet. They provide special facilities for conversion, interesting, but we'd better understand primitives first, then extend to objects in the next steps. +```smart header="Not covering objects yet" +In this chapter we don't cover objects yet. Here we study primitives first, and then we'll add objects in the chapter [todo]. ``` -[todo where? link?] +[todo where we cover them? link?] ## ToString @@ -64,7 +58,7 @@ alert(typeof str); // string let n = Number(str); // becomes a number 123 -alert(typeof n); // number +alert(typeof n); // number ``` The explicit conversion is usually required when we read a value coming from a text form field or another string-based source, but we expect a number to be entered. @@ -116,12 +110,12 @@ That only happens when one of arguments is a string. Otherwise values are conver Boolean conversion is the simplest one. -It happens in logical operations (later we'll meet condition tests and other kinds), but also can be performed manually with the call of `Boolean(value)`. +It happens in logical operations (later we'll meet condition tests and other kinds of them), but also can be performed manually with the call of `Boolean(value)`. The conversion rule: -- Values that are intuitively "empty", like `0`, an empty string, `null`, `undefined` and `NaN` become `false`. -- Other values become `true`. +- Values that are intuitively "empty", like `0`, an empty string, `null`, `undefined` and `NaN` become `false`. +- Other values become `true`. For instance: @@ -145,33 +139,39 @@ alert( Boolean(" ") ); // also true (any non-empty string is true) ## Summary +There exist three most widely used type conversions: to string, to number and to boolean. -- `ToString` -- happens in output, can be called with `String(value)`. +`ToString` +: Happens when we output something, can be performed with `String(value)`. The conversion to string is usually obvious for primitive values. -The conversion to string is usully obvious for primitive values. +`ToNumber` +: Happens in math operations, can be performed with `Number(value)`. -- `ToNumber` -- happens in math operations, can be called with `Number(value)`. + The conversion follows the rules: -The conversion follows the rules: + | Value | Becomes... | + |-------|-------------| + |`undefined`|`NaN`| + |`null`|`0`| + |true / false | `1 / 0` | + | `string` | The string is read "as is", whitespaces from both sides are ignored. An empty string is `0`. An error gives `NaN`. | -| Value | Becomes... | -|-------|-------------| -|`undefined`|`NaN`| -|`null`|`0`| -|true / false | `1 / 0` | -| `string` | The string is read "as is", whitespaces from both sides are ignored. An empty string is `0`. An error gives `NaN`. | +ToBoolean +: Happens in logical operations, or can be performed with `Boolean(value)`. -- ToBoolean -- happens in logical operatiosn, can be called with `Boolean(value)`. + Follows the rules: + + | Value | Becomes... | + |-------|-------------| + |`0`, `null`, `undefined`, `NaN`, `""` |`false`| + |any other value| `true` | -| Value | Becomes... | -|-------|-------------| -|`0`, `null`, `undefined`, `NaN`, `""` |`false`| -|any other value| `true` | Most of these rules are easy to understand and memorize. The notable exceptions where people usually make mistakes are: - `undefined` is `NaN` as a number. - `"0"` is true as a boolean. -Objects are not covered here, we'll return to them in the special object-only chapter. +Objects are not covered here, we'll return to them in the special chapter, devoted exclusively to objects. +[todo link?] diff --git a/1-js/2-first-steps/07-operators/article.md b/1-js/2-first-steps/07-operators/article.md index c3ddeef9..e5dcd088 100644 --- a/1-js/2-first-steps/07-operators/article.md +++ b/1-js/2-first-steps/07-operators/article.md @@ -8,9 +8,9 @@ In this chapter we concentrate on aspects that are not covered by the school ari ## Terms: "unary", "binary", "operand" -Before we move on, let's make a dip in the common terminology, used in the development. +Before we move on, let's grasp the common terminology. -- *An operand* -- is what operators are applied to. For instance in multiplication `5 * 2` there are two operands: the left operand is `5`, and the right operand is `2`. Sometimes operands are called "arguments". +- *An operand* -- is what operators are applied to. For instance in multiplication `5 * 2` there are two operands: the left operand is `5`, and the right operand is `2`. Sometimes people say "arguments" instead of "operands". - An operator is *unary* if it has a single operand. For example, the unary minus `"-"` reverses the sign of the number: ```js run @@ -32,7 +32,7 @@ Before we move on, let's make a dip in the common terminology, used in the devel ## Strings concatenation, binary + -Now let's get into Javascript specials. +Now let's see special features of Javascript operators, beyond school arithmetics. Usually the plus operator `'+'` sums numbers. @@ -40,10 +40,10 @@ But if the binary `+` is applied to strings, it merges (concatenates) them: ```js let s = "my" + "string"; -alert( s ); // mystring +alert(s); // mystring ``` -If one of operands of `+` is a string, then the other one is converted to string too. +Note that if any of operands is a string, then the other one is converted to string too. For example: @@ -52,7 +52,7 @@ alert( '1' + 2 ); // "12" alert( 2 + '1' ); // "21" ``` -Note that it doesn't matter whether the first operand is a string or the second one. The rule is simple: if any of operands is a string, then convert the other one into a string as well. +See, it doesn't matter whether the first operand is a string or the second one. The rule is simple: if any of operands is a string, then convert the other one into a string as well. The string concatenation and conversion is the special feature of the binary plus `"+"`. Other arithmetic operators work only with numbers. They always convert their operands to numbers. @@ -81,12 +81,12 @@ alert( +y ); // -2 *!* // Converts non-numbers -alert( +true ); // 1 +alert( +true ); // 1 alert( +"" ); // 0 */!* ``` -It actually does the same as `Number(true)` or `Number("")`, but shorter. +It actually does the same as `Number(...)`, but shorter. A need to convert string to number arises very often. For example, if we are getting values from HTML form fields, then are usually strings. @@ -107,13 +107,13 @@ If we want to treat them as numbers, then we can convert and then sum: let apples = "2"; let oranges = "3"; -alert( Number(apples) + Number(oranges) ); // 5 - *!* -// or the shorter variant: // both values converted to numbers before the binary plus alert( +apples + +oranges ); // 5 */!* + +// the longer variant +// alert( Number(apples) + Number(oranges) ); // 5 ``` From a mathematician's standpoint the abundance of pluses may seem strange. But from a programmer's standpoint -- there's nothing special: unary pluses are applied first, they convert strings to numbers, and then the binary plus sums them up. @@ -122,16 +122,15 @@ Why are unary pluses applied to values before the binary one? As we're going to ## Operators precedence -If an expression has more than one operator, the execution order is defined by their *precedence*, that is an implicit order among the operators. +If an expression has more than one operator, the execution order is defined by their *precedence*, or, in other words, there's an implicit priority order among the operators. From the school we all know that the multiplication in the expression `1 + 2 * 2` should be calculated before the addition. That's exactly the precedence thing. The multiplication is said to have *a higher precedence* than the addition. Brackets override any precedence, so if we're not satisfied with the order, we can use them, like: `(1 + 2) * 2`. -There are many operators in JavaScript. For clarity and internal needs there exists a [precedence table](https://developer.mozilla.org/en/JavaScript/Reference/operators/operator_precedence). Every operator has a corresponding precedence number. The one with the bigger number executes first. If the precedence is same -- the execution order is from left to right. - -An extract from the table: +There are many operators in JavaScript. Every operator has a corresponding precedence number. The one with the bigger number executes first. If the precedence is same -- the execution order is from left to right. +An extract from the [precedence table](https://developer.mozilla.org/en/JavaScript/Reference/operators/operator_precedence): | Precedence | Name | Sign | |------------|------|------| @@ -146,7 +145,7 @@ An extract from the table: | 3 | assignment | `=` | | ... | ... | ... | -As we can see, the "unary plus" has a priority of `15`, higher than `13` for the "addition" (binary plus). That's why in the expression `+apples + +oranges` unary pluses worked first, and then the addition. +As we can see, the "unary plus" has a priority of `15`, higher than `13` for the "addition" (binary plus). That's why in the expression `"+apples + +oranges"` unary pluses work first, and then the addition. ## Assignment @@ -177,7 +176,7 @@ alert( c ); // 4 Assignments always evaluate the right value first, then assign it to the left one. So the chain of assignments is executed from right to left: the rightmost expression `2+2` is calculated first, assigned to `c`, then `b = c` works, thus assigning it to `b`, and then `a = b`. At the end, all variables share a single value. ````smart header="The assignment operator `\"=\"` returns a value" -An operator always returns a value. That's obvious for most of them like an addition `+` or a multiplication `*`. But the assignment follows that rule too. +An operator always returns a value. That's obvious for most of them like an addition `+` or a multiplication `*`. But the assignment operator follows that rule too. The call `x = value` writes the `value` into `x` *and then returns it*. @@ -197,7 +196,7 @@ alert( c ); // 0 In the example above, the result of `(a = b + 1)` is the value which is assigned to `a` (that is `3`). It is then used to substract from `3`. -Funny code, isn't it? We should understand how it works, but don't write anything like that ourselves. Such tricks definitely don't make the code clearer and more readable. +Funny code, isn't it? We should understand how it works, because sometimes we can see it in 3rd-party libraries, but don't write anything like that ourselves. Such tricks definitely don't make the code clearer and more readable. ```` ## Remainder % @@ -218,7 +217,7 @@ alert( 6 % 3 ); // 0 is a remainder of 6 divided by 3 The exponentiation operator `**` is a recent addition to the language. Not all browsers support it yet. -For a natural number `b`, the result of `a ** b` is `a` multiplied by itself `b` times. +For a natural number `b`, the result of `a ** b` is `a` multiplied by itself `b` times. For instance: @@ -263,7 +262,7 @@ Increment/decrement can be applied only to a variable. An attempt to use it on a Operators `++` and `--` can be placed both after and before the variable. -- When the operator goes after the variable, it is called a "postfix form": `counter++`. +- When the operator goes after the variable, it is called a "postfix form": `counter++`. - The "prefix form" is when the operator stands before the variable: `++counter`. Both of these records do the same: increase `i` by `1`. diff --git a/1-js/2-first-steps/08-comparison/article.md b/1-js/2-first-steps/08-comparison/article.md index 75e69602..fa8c5d4b 100644 --- a/1-js/2-first-steps/08-comparison/article.md +++ b/1-js/2-first-steps/08-comparison/article.md @@ -31,7 +31,7 @@ let result = 5 > 4; // assign the result of the comparison alert( result ); // true ``` -## Strings comparison +## String comparison To see which string is greater than the other, the so-called "dictionary" or "lexicographical" order is used. @@ -47,7 +47,7 @@ alert( 'Bee' > 'Be' ); // true The algorithm to compare two strings is simple: -1. Compare the first characters of both strings. +1. Compare first characters of both strings. 2. If the first one is greater(or less), then the first string is greater(or less) than the second and we're done. 3. Otherwise if first characters are equal, compare the second characters the same way. 4. Repeat until the end of any string. @@ -61,15 +61,15 @@ Strings `"Glow"` and `"Glee"` are compared character-by-character: 2. `l` is the same as `l`. 3. `o` is greater than `e`. Stop here. The first string is greater. -```smart header="Not a dictionary, but Unicode" +```smart header="Not a real dictionary, but Unicode order" The comparison algorithm given above is roughly equivalent to the one used in book dictionaries or phone books. But it's not exactly the same. -For instance, the case matters. A capital letter `"A"` is not equal to the lowercase `"a"`. Which one is greater? Actually, the lowercase `"a"` is. Why? Because the lowercase character has a greater index in the internal encoding table (Unicode). We'll get back to specific details and consequences in the chapter . +For instance, case matters. A capital letter `"A"` is not equal to the lowercase `"a"`. Which one is greater? Actually, the lowercase `"a"` is. Why? Because the lowercase character has a greater index in the internal encoding table (Unicode). We'll get back to specific details and consequences in the chapter . ``` ## Comparison of different types -When compared values belong to different types, they are coerced to numbers. +When compared values belong to different types, they are converted to numbers. For example: @@ -140,7 +140,7 @@ The string equality check operator is a bit longer to write, but makes more obvi ## Comparison with null and undefined -Let's see more corner cases. +Let's see more corner cases. There's a non-intuitive behavior when `null` or `undefined` is compared with other values. @@ -152,7 +152,7 @@ For a non-strict check `null == undefined` : There's a special rule. These two are a "sweet couple": they equal each other (in the sense of `==`), but no any other value. For maths and evaluation of other comparisons `< > <= >=` -: Values `null/undefined` are converted to a number: `null` becomes `0`, while `undefined` becomes `NaN`. +: Values `null/undefined` are converted to a number: `null` becomes `0`, while `undefined` becomes `NaN`. Now let's see funny things that happen when we apply those rules. And, what's more important, how do not fall into a trap with unobvious language features. @@ -204,4 +204,3 @@ Don't use comparisons `>= > < <=` with a variable which may be `null/undefined`, - When values of different types are compared, they get converted to numbers (with the exclusion of a strict equality check). - Values `null` and `undefined` equal `==` each other and do not equal any other value. - Be careful when using comparisons like `>` or `<` with variables that can occasionaly be `null/undefined`. Making a separate check for `null/undefined` is a good idea. - diff --git a/1-js/2-first-steps/09-uibasic/article.md b/1-js/2-first-steps/09-uibasic/article.md index b48e248b..b9f23a30 100644 --- a/1-js/2-first-steps/09-uibasic/article.md +++ b/1-js/2-first-steps/09-uibasic/article.md @@ -1,8 +1,10 @@ # Interaction: alert, prompt, confirm -This chapter covers basic UI operations: `alert`, `prompt` and `confirm`. They allow to ask a visitor for the input and show the results. +This part of the tutorial aims to cover Javascript "as is", without environment-specific tweaks. -They are browser-specific. For other environments like Node.JS there are other ways of getting the information. Also they are very simple, so we can use them for the start. +But still we use a browser as the demo environment. So we should know at least few user-interface functions. + +In this chapter we'll get familiar with the browser-specific functions `alert`, `prompt` and `confirm`. [cut] @@ -11,7 +13,7 @@ They are browser-specific. For other environments like Node.JS there are other w Syntax: ```js -alert(message) +alert(message); ``` This shows a message and pauses the script execution until the user presses "OK". @@ -29,27 +31,27 @@ The small window with the message is called a *modal window*. The word "modal" m Function `prompt` accepts two arguments: ```js no-beautify -result = prompt(title, default); +result = prompt(title[, default]); ``` -It shows a modal window with the given `title`, a field for text, initially filled with the `default` string and buttons OK/CANCEL. +It shows a modal window with a field for text and buttons OK/CANCEL. -The visitor may type something in the field and press OK. Or he can cancel the input by pressing a CANCEL button or the `key:Esc` key. +`title` +: Is a modal window title -The call to `prompt` returns the text from the field or `null` if te input is canceled. +`default` +: An optional second parameter, the initial value for the text field. -```warn header="Safari does not return `null`" -Safari returns an empty string instead of `null` on cancellation. So we can't be sure whether the user actually entered an empty line or he cancelled the input. +The visitor may type something in the field and press OK. Or he can cancel the input by pressing a CANCEL button or hitting the `key:Esc` key. -A compatible practice is to treat both an empty line and `null` the same, as a cancellation. -``` +The call to `prompt` returns the text from the field or `null` if the input is canceled. As with `alert`, the `prompt` window is modal. ```js run let age = prompt('How old are you?', 100); -alert(`You are ${age} years old!`); // You are 100 years old! +alert(`You are ${age} years old!`); // You are 100 years old! ``` ````warn header="IE: always supply a `default`" @@ -96,7 +98,7 @@ alert( isBoss ); // true is OK is pressed `prompt` : shows a message asking the user to input text. It returns the text or, if CANCEL or `key:Esc` is clicked, all browsers except Safari return `null`. -`confirm` +`confirm` : shows a message and waits the user to press "OK" or "CANCEL". It returns `true` for OK and `false` for CANCEL/`key:Esc`. There are two limitations shared by all the methods above: diff --git a/1-js/2-first-steps/12-while-for/7-list-primes/solution.md b/1-js/2-first-steps/12-while-for/7-list-primes/solution.md index 5234fa44..e7738947 100644 --- a/1-js/2-first-steps/12-while-for/7-list-primes/solution.md +++ b/1-js/2-first-steps/12-while-for/7-list-primes/solution.md @@ -14,7 +14,7 @@ The code using a label: ```js run nextPrime: -for (let i = 2; i < 10; i++) { // for each i... +for (let i = 2; i <= 10; i++) { // for each i... for (let j = 2; j < i; j++) { // look for a divisor.. if (i % j == 0) continue nextPrime; // not a prime, go next i diff --git a/1-js/2-first-steps/12-while-for/article.md b/1-js/2-first-steps/12-while-for/article.md index 314683b9..be7bd353 100644 --- a/1-js/2-first-steps/12-while-for/article.md +++ b/1-js/2-first-steps/12-while-for/article.md @@ -95,50 +95,71 @@ for (begin; condition; step) { } ``` -Let's see these parts in an example. The loop below runs `alert(i)` for `i` from `0` up to (but not including) `3`: +Let's see these parts in an example. For instance, the loop below runs `alert(i)` for `i` from `0` up to (but not including) `3`: ```js run -let i; - -for (i = 0; i < 3; i++) { // shows 0, then 1, then 2 - alert( i ); +for (let i = 0; i < 3; i++) { // shows 0, then 1, then 2 + alert(i); } ``` -Let's split the last example into parts: +Let's examine the last example part-by-part: -begin: `i=0` -: Executes once upon entering the loop. +| part | | | +|-------|----------|----------------------------------------------------------------------------| +| begin | `i=0` | Executes once upon entering the loop. | +| condition | `i<3`| Checked before every loop iteration, if fails the loop stops. | +| body | `alert(i)`| Runs again and again while the condition is truthy | +| step| `i++` | Executes after the body on each iteration, but before the condition check. | -condition: `i<3` -: Checked before every loop iteration, if fails the loop stops. -body: `alert(i)` -: Runs again and again while the condition is truthy - -step: `i++` -: Executes after the body on each iteration, but before the condition check. - -The execution flow is: +The general loop algorithm works like this: ``` Begin - → (if condition → run body and run step) - → (if condition → run body and run step) - → ... repeat until the condition is falsy. +→ (if condition → run body and run step) +→ ... repeat while the condition is truthy +``` + +If you are new to loops, then maybe it would help if you go back to the example and reproduce how it runs step-by-step on a piece of paper. + +That's what exactly happens in our case: + +```js +// for (let i = 0; i < 3; i++) alert(i) + +// begin +let i = 0 +// if condition → run body and run step +if (i < 3) { alert(i); i++ } +// repeat while the condition is truthy +if (i < 3) { alert(i); i++ } +if (i < 3) { alert(i); i++ } +// ...finish, because now i == 3 ``` ````smart header="Inline variable declaration" -We can declare a "counter" variable right in the beginning of the loop. +Here the "counter" variable `i` is declared right in the the loop. That's called an "inline" variable declaration. Such variable is visible only inside the loop. -```js run no-beautify +```js run for (*!*let*/!* i = 0; i < 3; i++) { alert(i); // 0, 1, 2 } +alert(i); // error, no such variable +``` + +We can use an existing variable as well: + +```js run +let i = 0; +for (i = 0; i < 3; i++) { // use an existing variable + alert(i); // 0, 1, 2 +} +alert(i); // 3, visible, because declared outside of the loop ``` -The variable will be visible only inside the loop. ```` + ### Skipping parts Any part of the `for` can be skipped. @@ -148,15 +169,13 @@ For example, we can omit `begin` if we don't need to do anything at the loop sta Like here: ```js run -let i = 0; +let i = 0; // imagine we have i already declared and assigned -for (; i < 3; i++) { +for (; i < 3; i++) { // no need for "begin" alert( i ); // 0, 1, 2 } ``` -It would work same as `for(let i=0; ...)`. - We can also remove the `step` part: ```js run @@ -164,10 +183,11 @@ let i = 0; for (; i < 3;) { alert( i ); - // the loop became identical to while (i<3) } ``` +The loop became identical to `while (i<3)`. + We can actually remove everything, thus creating an infinite loop: ```js @@ -176,7 +196,7 @@ for (;;) { } ``` -Please note that the semicolons `;` must present, otherwise it would be a syntax error. +Please note that the two `for` semicolons `;` must present, otherwise it would be a syntax error. ## Breaking the loop @@ -218,7 +238,7 @@ The loop above uses `continue` to output only odd values: ```js run no-beautify for (let i = 0; i < 10; i++) { - // if true, skip the remaining part of the body + // if true, skip the remaining part of the body *!*if (i % 2 == 0) continue;*/!* alert(i); // 1, then 3, 5, 7, 9 @@ -362,4 +382,3 @@ To make an "infinite" loop, usually the `while(true)` construct is used. Such a If we don't want to do anything more on this iteration and would like to forward on to the next one -- the `continue` directive does it. `Break/continue` support labels before the loop. A label is the only way for `break/continue` to escape the nesting and go to the outer loop. - diff --git a/1-js/2-first-steps/14-function-basics/article.md b/1-js/2-first-steps/14-function-basics/article.md index 1c9365a2..6eab133c 100644 --- a/1-js/2-first-steps/14-function-basics/article.md +++ b/1-js/2-first-steps/14-function-basics/article.md @@ -141,9 +141,8 @@ We can pass arbitrary data to function using it's parameters (also called *funct In the example below, the function has two parameters: `from` and `text`. -```js run no-beautify +```js run function showMessage(*!*from, text*/!*) { // arguments: from, text - alert(from + ': ' + text); } @@ -153,7 +152,7 @@ showMessage('Ann', "What's up?"); // Ann: What's up? */!* ``` -When the function is called, the values in the brackets are copied to local variables `from` and `next`. +When the function is called, the values in the brackets are copied to local variables `from` and `next`. Please note that because the function can modify them. The changes are made to copies, so they won't affect anything outside: @@ -188,9 +187,31 @@ showMessage("Ann"); That's not an error. Such call would output `"Ann: undefined"`, because `text === undefined`. -If we want to track when the function is called with a single argument and use a "default" value in this case, then we can check if `text` is defined, like here: +If we want to use a "default" `text` in this case, then we can specify it after `=`: ```js run +function showMessage(from, *!*text = 'no text given'*/!*) { + alert( from + ": " + text ); +} + +showMessage("Ann"); // Ann: no text given +``` + +Here `'no text given'` is a string, but it can be a more complex expression, which is only evaluated and assigned if the parameter is missing. So, this is also possible: + +```js run +function showMessage(from, text = anotherFunction()) { + // anotherFunction() only executed if no text given +} +``` + + +````smart header="Default parameters old-style" +Old editions of Javascript did not support default parameters. So there are alternative ways to support them, that you can find mostly in the old scripts. + +For instance, an explicit check for being `undefined`: + +```js function showMessage(from, text) { *!* if (text === undefined) { @@ -200,43 +221,19 @@ function showMessage(from, text) { alert( from + ": " + text ); } - -showMessage("Ann", "Hello!"); // Ann: Hello! -*!* -showMessage("Ann"); // Ann: no text given -*/!* ``` -There are also other ways to supply "default values" for missing arguments: +...Or operator `||`: -- Use operator `||`: +```js +function showMessage(from, text) { + // the argument is considered missing if it's falsy + text = text || 'no text given'; + ... +} +``` +```` - ```js - function showMessage(from, text) { - text = text || 'no text given'; - ... - } - ``` - - This way is shorter, but the argument is considered missing even if it exists, but is falsy, like an empty line, `0` or `null`. - -- Specify the default value after `=`: - - ```js run - function showMessage(from, *!*text = 'no text given'*/!*) { - alert( from + ": " + text ); - } - - showMessage("Ann"); // Ann: no text given - ``` - - Here `'no text given'` is a string, but it can be a more complex expression, which is only evaluated and assigned if the parameter is missing. So, this is also possible: - - ```js run - function showMessage(from, text = anotherFunction()) { - // anotherFunction() runs if no text given - } - ``` ## Returning a value @@ -266,7 +263,7 @@ function checkAge(age) { } else { *!* return confirm('Got a permission from the parents?'); -*/!* +*/!* } } @@ -338,7 +335,7 @@ So, it effectively becomes an empty return. We should put the value on the same Functions are actions. So their name is usually a verb. It should briefly, but as accurately as possible describe what the function does. So that a person who reads the code gets the right clue. -It is a widespread practice to start a function with a verbal prefix which vaguely describes the action. There must be an agreement within the team on the meaning of the prefixes. +It is a widespread practice to start a function with a verbal prefix which vaguely describes the action. There must be an agreement within the team on the meaning of the prefixes. For instance, functions that start with `"show"` -- usually show something. @@ -410,4 +407,3 @@ Function naming: - There is a bunch of commonly adapted verbal prefixes like `create…`, `show…`, `get…`, `check…` etc which can help. The main point is to be consistent about their meaning. Functions are the main building blocks of scripts. Now we covered the basics, so we actually can start creating and using them. But that's only the beginning of the path. We are going to return to them many times, going more deeply in their advanced features. - diff --git a/1-js/2-first-steps/15-function-expressions-arrows/article.md b/1-js/2-first-steps/15-function-expressions-arrows/article.md index 6426d3bb..2a232f05 100644 --- a/1-js/2-first-steps/15-function-expressions-arrows/article.md +++ b/1-js/2-first-steps/15-function-expressions-arrows/article.md @@ -1,6 +1,6 @@ # Function expressions and arrows -In Javascript a function is not a "magical language structure", but a special kind of value. +In Javascript a function is not a "magical language structure", but a special kind of value. The syntax that we used before is called *Function Declaration*: @@ -92,7 +92,7 @@ let sayHi = function() { The answer is simple: - There's no need in `;` at the end of code blocks and syntax structures that use them like `if { ... }`, `for { }`, `function f { }` etc. -- The Function Expression appears in the context of the statement: `let sayHi = value;`. It's not a code block. The semicolon `;` is recommended at the end of statements, no matter what is the `value`. So the semicolon here is not related to Function Expression itself in any way, it just terminates the statement. +- A Function Expression is used inside the statement: `let sayHi = ...;`, as a value. It's not a code block. The semicolon `;` is recommended at the end of statements, no matter what is the value. So the semicolon here is not related to Function Expression itself in any way, it just terminates the statement. ```` ## Anonymous functions @@ -163,7 +163,7 @@ Regular values like strings or numbers represent the *data*. A function can be perceived as an *action*. -We can pass it between variables and run when we want. +We can pass it between variables and run when we want. ``` @@ -197,11 +197,11 @@ The more subtle difference is when they are actualy created by the JavaScript en That's kind of obvious. Once the execution flow passes to the right side of the assignment `let sum = function` -- here we go, the function is created and can be used (assigned, called etc) from now on. -Function Declarations are different. +Function Declarations are different. **Function Declarations are usable in the whole script/code block.** -In other words, when JavaScript *prepares* to run the script/code block, it first looks for Function Declarations in it and creates the functions. We can think of it as an "initialization stage". +In other words, when JavaScript *prepares* to run the script/code block, it first looks for Function Declarations in it and creates the functions. We can think of it as an "initialization stage". And after all Function Declarations are processed, it actually executes it. @@ -268,7 +268,7 @@ welcome(); // Error: welcome is not defined */!* ``` -The Function Declaration is visible only inside the code block where it resides. +The Function Declaration is visible only inside the code block where it resides. We can call it from within the block, but not from outside: @@ -281,7 +281,7 @@ if (age < 18) { */!* // | function welcome() { // | - alert("Hello!"); // | Function Declaration is available + alert("Hello!"); // | Function Declaration is available } // | everywhere in the block when it's declared // | *!* @@ -291,7 +291,7 @@ if (age < 18) { } else { // \ function welcome() { // | - alert("Greetings!"); // | in this if test we don't enter this block, + alert("Greetings!"); // | in this if test we don't enter this block, } // | so this "welcome" is never created // / } @@ -304,7 +304,7 @@ welcome(); // Error: welcome is not defined */!* ``` -What can we do to make `welcome` visible outside? +What can we do to make `welcome` visible outside? The right thing would be to use a Function Expression and assign `welcome` to the variable which is declared outside of `if` and has the proper visibility: @@ -347,7 +347,7 @@ welcome(); // ok now ```smart header="What to choose: a Declaration or an Expression?" -As a rule of thumb, a Function Declaration is prefered. It gives more freedom in how to organize our code, because we can call it both above and below. +As a rule of thumb, a Function Declaration is prefered. It gives more freedom in how to organize our code, because we can call it both above and below. It's also a little bit easier to look up Function Declarations in the code, they increase readability of the code. @@ -359,7 +359,7 @@ But if a Function Declaration does not fit for some reason (we've seen an exampl Enough with the complexities for now. Let's relax with another syntax of functions that can make our code shorter. -Arrow functions act like a function expression, but look a little bit differently. +Arrow functions act like a function expression, but look a little bit differently. The syntax is: @@ -396,7 +396,7 @@ let sum = function(a, b) { If we have only one argument, then brackets can be omitted, making that even shorter: ```js run -// same as +// same as // let double = function(n) { return n*2 } *!* let double = n => n*2; @@ -421,7 +421,7 @@ Arrow functions are very convenient for simple one-line actions, when we're just ```smart header="Multiline arrow functions" -The examples above took arguments from the left of `=>` and evaluate the right-side expression with them. +The examples above took arguments from the left of `=>` and evaluate the right-side expression with them. Sometimes we need something a little bit more complex, like multiple expressions or statements. It is also possible, but we should enclose them in figure brackets. Then use a normal `return` within them. @@ -439,7 +439,7 @@ alert( sum(1, 2) ); // 3 ``` ```smart header="More to come" -Here we praised arrow functions for shortness. But that's not all! Arrow functions have other interesting features in them. We'll return to them later and see where else they shine. +Here we praised arrow functions for shortness. But that's not all! Arrow functions have other interesting features. We'll return to them later and see where else they shine. As for now, we can already use them for one-line actions. ``` @@ -453,7 +453,7 @@ As for now, we can already use them for one-line actions. - If the function is created as a part of an expression -- it's a Function Expression. - Function Declarations are processed before the code block is executed. They are visible everywhere in the block (or the script). - Function Expressions are created when the execution flow reaches them. -- Function Expressions allow to specify an optional name for internal needs (Named Function Expression). +- Function Expressions allow to specify an optional name for internal needs (Named Function Expression). If we simple want to create a function, then in most cases Function Declaration is preferable. diff --git a/1-js/2-first-steps/16-javascript-specials/article.md b/1-js/2-first-steps/16-javascript-specials/article.md index 5b18f49f..cc69e119 100644 --- a/1-js/2-first-steps/16-javascript-specials/article.md +++ b/1-js/2-first-steps/16-javascript-specials/article.md @@ -1,5 +1,7 @@ # JavaScript specials: all together +[todo finish me. is this needed?] + This chapter aims to list features of JavaScript that we've learned, paying special attention to unobvious moments. That's especially useful if you came from another language or, just as a recap. @@ -57,7 +59,7 @@ To fully enable all features of modern JavaScript, we should start scripts with The directive must be at the top of a script or at the beginning of a function. -Without `"use strict"`, everything still works, but some features behave in old-fasion, "compatible" way. We'd generally prefer the modern behavior. +Without `"use strict"`, everything still works, but some features behave in old-fasion, "compatible" way. We'd generally prefer the modern behavior. Later we'll get acquanted with advanced features of the language that enable strict mode implicitly. @@ -72,7 +74,7 @@ Can be declared using: - `var` (old-style, will see later) A variable name can include: -- Letters and digits, but the first character may not be a digit. +- Letters and digits, but the first character may not be a digit. - Characters `$` and `_` are normal, on par with letters. - Non-latin alphabets and hieroglyphs are also allowed, but commonly not used. @@ -83,7 +85,7 @@ let x = 5; x = "John"; ``` -There are 7 data types: +There are 7 data types: - `number` for both floating-point and integer numbers, - `string` for strings, @@ -147,10 +149,10 @@ Ternary : The only operator with three parameters: `cond ? resultA : result B` Logical operators -: Logical AND `&&` and OR `||` perform short-circuit evaluation and then return the value where it stopped. +: Logical AND `&&` and OR `||` perform short-circuit evaluation and then return the value where it stopped. Comparisons -: Equality check `===` immediately fails if types are different. +: Equality check `===` immediately fails if types are different. Other comparisons perform type conversions, usually to a number: @@ -159,7 +161,7 @@ Comparisons alert( true > 0 ); // true ``` - Values `null` and `undefined` are special: they equal `==` each other and don't equal anything else. + Values `null` and `undefined` are special: they equal `==` each other and don't equal anything else. Greater/less comparisons compare strings character-by-character, other types are converted to a number. diff --git a/1-js/4-object-basics/01-object/article.md b/1-js/4-object-basics/01-object/article.md index f607428e..af69005a 100644 --- a/1-js/4-object-basics/01-object/article.md +++ b/1-js/4-object-basics/01-object/article.md @@ -1,5 +1,5 @@ -# Objects +# Objects As we know, there are 7 language types in Javascript. Six of them are called "primitive", because their values contain only a single thing (be it a string or a number or whatever). @@ -7,7 +7,7 @@ In contrast, objects are used to store keyed collections of various data and mor [cut] -An object can be created with figure brackets `{…}` with an optional list of "key: value" pairs. In programming that's sometimes called an "associative array" or a "hash". +An object can be created with figure brackets `{…}` with an optional list of *properties*. A property is a "key: value" pair, where `key` is a string (also called a "property name"), and `value` can be anything. We can imagine an object as a cabinet with signed files. Every piece of data is stored in it's file by the key. It's easy to find a file by it's name or add/remove a file. @@ -26,7 +26,7 @@ Usually, the figure brackets `{...}` are used. That declaration is called an *ob ## Literals and properties -We can immediately put some data into `{...}` as "key: value" pairs. Every pair is called *an object property*: +We can immediately put some properties into `{...}` as "key: value" pairs: ```js let user = { // an object @@ -35,15 +35,15 @@ let user = { // an object }; ``` -A property has an identifier (also "name" and "key") before the colon `":"` and a value to the right of it. +A property has a key (also known as "name" and "identifier") before the colon `":"` and a value to the right of it. In the `user` object, there are two properties: -1. The first property has the name `"name"` and the value `"John"`. +1. The first property has the name `"name"` and the value `"John"`. 2. The second one has the name `"age"` and the value `30`. The resulting `user` object can be imagined as a cabinet with two signed files labelled "name" and "age". - + ![user object](object-user.png) We can add, remove and read files from it any time. @@ -56,15 +56,15 @@ alert( user.name ); // John alert( user.age ); // 30 ``` -A value can be of any time, let's add a boolean one: +The value can be of any type. Let's add a boolean one: ```js -user.isAdmin = true; +user.isAdmin = true; ``` ![user object 2](object-user-isadmin.png) -...And remove `age` with the help of `delete` operator: +To remove a property, we can use `delete` operator: ```js delete user.age; @@ -74,47 +74,73 @@ delete user.age; We can also use multiword property names, but then they must be quoted: -```js +```js let user = { name: "John", age: 30, "likes birds": true // multiword property name must be quoted -}; +}; ``` ![](object-user-props.png) + +````smart header="Trailing comma" +The last property in the list may end with a comma: +```js +let user = { + name: "John", + age: 30*!*,*/!* +} +``` +That is called a "trailing" or "hanging" comma. Makes it easier to add/remove/move around properties, because all lines become alike. +```` + ## Square brackets For multiword properties, the dot access won't work: -```js +```js run // this would give a syntax error user.likes birds = true ``` -That's because the dot requires the key to be a valid variable identifier. That is: no spaces and other limitations. +That's because the dot requires the key to be a valid variable identifier. That is: no spaces and other limitations. There's an alternative "square bracket notation" that works with any string: -```js + +```js run +let user = {}; + +// set user["likes birds"] = true; + +// get +alert(user["likes birds"]); // true + +// delete +delete user["likes birds"]; ``` -Square brackets are also the way to access a property by the name from the variable: +Now everything is fine. Please note that the string inside the brackets is properly quoted (any type of quotes will do). + +Square brackets are also provide a way to access a property by the name from the variable: ```js let key = "likes birds"; -user[key] = true; // same as above + +// same as user["likes birds"] = true; +user[key] = true; ``` -The square brackets mean: "take the property name from the variable". +Here, the variable `key` may be calculated at run-time or depend on the user input. And then we use it to access the property. That gives us a great deal of flexibility. The dot notation cannot be used in similar way. -That variable can be assigned at run-time, for instance: +For instance: ```js run let user = { - name: "John", + name: "John", age: 30 }; @@ -124,9 +150,12 @@ let key = prompt("What do you want to know about the user?", "name"); alert( user[key] ); // John (if enter "name") ``` + ### Computed properties -*Computed properties* are square brackets used inside an object literal: +We can use square brackets in an object literal. That's called *computed properties*. + +For instance: ```js run let fruit = prompt("Which fruit to buy?", "apple"); @@ -140,7 +169,9 @@ let bag = { alert( bag.apple ); // 5 if fruit="apple" ``` -Here, the value of `fruit` variable is used as the property name. So, if a visitor enters `"apple"`, `bag` will become `{apple: 5}`. +The meaning of a computed property is simple: `[fruit]` means that the property name should be taken from `fruit`. + +So, if a visitor enters `"apple"`, `bag` will become `{apple: 5}`. Essentially, that works the same as: ```js run @@ -148,10 +179,12 @@ let fruit = prompt("Which fruit to buy?", "apple"); let bag = {}; // take property name from the fruit variable -bag[fruit] = 5; +bag[fruit] = 5; ``` -We can use more complex expressions inside square brackets. Anything that results in a property name: +...But looks nicer. + +We can use more complex expressions inside square brackets: ```js let fruit = 'apple'; @@ -160,26 +193,16 @@ let bag = { }; ``` -Square brackets are much more powerful than the dot notation. They allow any property names and variables. But they are more cumbersome to write. So most of the time, when property names are known and simple, the dot is used. And if we need something more complex, then we switch to square brackets. +Square brackets are much more powerful than the dot notation. They allow any property names and variables. But they are also more cumbersome to write. +So most of the time, when property names are known and simple, the dot is used. And if we need something more complex, then we switch to square brackets. -````smart header="Trailing comma" -The last property in the list may end with a comma: -```js -let user = { - name: "John", - age: 30*!*,*/!* -} -``` -That is called a "trailing" or "hanging" comma. Makes it easier to add/remove/move around properties, because all lines become alike. -```` - ````smart header="Reserved words are allowed as property names" A variable cannot have a name equal to one of language-reserved words like "for", "let", "return" etc. -But for an object property, there's no such restruction. Any name is fine: +But for an object property, there's no such restriction. Any name is fine: ```js run let obj = { @@ -194,11 +217,12 @@ alert( obj.for + obj.let + obj.return ); // 6 Basically, any name is allowed, but there's a special one: `"__proto__"` that gets special treatment for historical reasons. For instance, we can't set it to a non-object value: ```js run -let obj = { __proto__: 5 }; +let obj = {}; +obj.__proto__ = 5; alert(obj.__proto__); // [object Object], didn't work as intended ``` -Later we'll learn more about that `__proto__` and see how to work that problem [todo Object.create(null)]. Also we'll learn another data structure [Map](info:map-set-weakmap-weakset) that doesn't have such problems and supports arbitrary keys. +As we see from the code, the assignment to a primitive `5` is ignored. If we want to store *arbitrary* (user-provided) keys, then such behavior can be the source of bugs and even vulnerabilities, because it's unexpected. There's another data structure [Map](info:map-set-weakmap-weakset), that we'll learn in the chapter , which supports arbitrary keys. ```` @@ -209,11 +233,10 @@ In real code we often use existing variables as values for property names. For instance: ```js run -function makeUser(name, age) { -*!* - // take values for name and age from variables -*/!* - return { +function makeUser() { + let name = prompt("Name?"); + let age = prompt("Age?"); + return { name: name, age: age }; @@ -223,7 +246,7 @@ let user = makeUser("John", 30); alert(user.name); // John ``` -In the example above, properties have same names as variables. There's a special shorthand notation that is shorter. +In the example above, properties have same names as variables. The use-case of making a property from a variable is so common, that there's a special *property value shorthand* to make it shorter. Instead of `name:name` we can just write `name`, like this: @@ -241,9 +264,9 @@ function makeUser(name, age) { We can use both normal properties and shorthands in the same object: ```js -let user = { +let user = { name, // same as name:name - age: 30 + age: 30 }; ``` @@ -258,9 +281,9 @@ let user = {}; alert( user.noSuchProperty === undefined ); // true means "no such property" ``` -There also exists a special operator `"in"` to check for the existance of a property. +There also exists a special operator `"in"` to check for the existance of a property. -The syntax is: +The syntax is: ```js "key" in object ``` @@ -274,7 +297,7 @@ alert( "age" in user ); // true, user.age exists alert( "blabla" in user ); // false, user.blabla doesn't exist ``` -Please note that at the left side of `in` there must be a *property name*. That's usually a quoted string. +Please note that at the left side of `in` there must be a *property name*. That's usually a quoted string. If we omit quotes, that would mean a variable containing the actual name to be tested. For instance: @@ -291,9 +314,9 @@ Usually, the strict comparison `"=== undefined"` check works fine. But there's a It's when an object property exists, but stores `undefined`: ```js run -let obj = { - test: undefined -}; +let obj = { + test: undefined +}; alert( obj.test ); // it's undefined, so - no such property? @@ -309,7 +332,7 @@ Situations like this happen very rarely, because `undefined` is usually not assi ## The "for..in" loop -To walk over all keys of an object, there exists a special form of the loop: `for..in`. This is a completely different thing from the `for(;;)` construct that we studied before. +To walk over all keys of an object, there exists a special form of the loop: `for..in`. This is a completely different thing from the `for(;;)` construct that we studied before. The syntax: @@ -336,16 +359,16 @@ for(let key in user) { } ``` -Note that all "for" constructs allow to declare the looping variable inside the loop, like `let key` here. +Note that all "for" constructs allow to declare the looping variable inside the loop, like `let key` here. Also, we could use another variable name here instead of `key`. For instance, `"for(let prop in obj)"` is also widely used. ### Ordered like an object -Are objects ordered? In other words, if we loop over an object, do we get all properties in the same order that they are added in it? +Are objects ordered? In other words, if we loop over an object, do we get all properties in the same order that they are added in it? Can we rely on it? -The short answer is: "ordered like an object": integer properties are sorted, others appear in creation order. The details follow. +The short answer is: "ordered in a special fashion": integer properties are sorted, others appear in creation order. The details follow. As an example, let's consider an object with the phone codes: @@ -367,7 +390,7 @@ for(let code in codes) { The object may be used to suggest a list of options to the user. If we're making a site mainly for German audience then we probably want `49` to be the first. -But if we run the code, we see a totally different picture: +But if we run the code, we see a totally different picture: - USA (1) goes first - then Switzerland (41) and so on. @@ -375,11 +398,12 @@ But if we run the code, we see a totally different picture: The phone codes go in the ascending sorted order, because they are integer. So we see `1, 41, 44, 49`. ````smart header="Integer properties? What's that?" -The "integer property" term here means a string that can be converted to-from integer without a change. +The "integer property" term here means a string that can be converted to-and-from integer without a change. So, "49" is an integer property name, because when it's transformed to an integer number and back, it's still the same. But "+49" and "1.2" are not: ```js run +// Math.trunc is a built-in function that removes the decimal part alert( String(Math.trunc(Number("49"))) ); // "49", same, integer property alert( String(Math.trunc(Number("+49"))) ); // "49", not same ⇒ not integer property alert( String(Math.trunc(Number("1.2"))) ); // "1", not same ⇒ not integer property @@ -417,15 +441,13 @@ let codes = { }; for(let code in codes) { - alert( +code ); // 49, 41, 44, 1 + alert( +code ); // 49, 41, 44, 1 } ``` -Now it works as intended. +Now it works as intended. - - -## References +## Copying by reference One of fundamental differences of objects vs primitives is that they are stored and copied "by reference". @@ -456,7 +478,7 @@ let user = { ![](variable-contains-reference.png) -Note that the object itself is stored somewhere in memory. The variable `user` has a "reference" to it. +Here, the object is stored somewhere in memory. And the variable `user` has a "reference" to it. **When an object variable is copied -- the reference is copied, the object is not duplicated.** @@ -465,7 +487,7 @@ If we imagine an object as a cabinet, then a variable is a key to it. Copying a For instance: ```js no-beautify -let user = { name: "John" }; +let user = { name: "John" }; let admin = user; // copy the reference ``` @@ -488,7 +510,7 @@ admin.name = 'Pete'; // changed by the "admin" reference alert(*!*user.name*/!*); // 'Pete', changes are seen from the "user" reference ``` -The example above demonstrates that there is only one object. Like if we had a cabinet with two keys and used one of them (`admin`) to get into it -- later using the other one (`user`) we will see things modified. +The example above demonstrates that there is only one object. Like if we had a cabinet with two keys and used one of them (`admin`) to get into it. Then, if we later use the other key (`user`) we see changes. ### Comparison by reference @@ -515,7 +537,7 @@ let b = {}; // two independent objects alert( a == b ); // false ``` -For comparisons like `obj1 > obj2` or for a comparison against a primitive `obj == 5`, objects are converted to primitives. We'll study how object conversions work very soon, but to say the truth, such comparisons occur very rarely in real code and usually are a result of a coding mistake. +For comparisons like `obj1 > obj2` or for a comparison against a primitive `obj == 5`, objects are converted to primitives. We'll study how object conversions work very soon, but to say the truth, such comparisons are necessary very rarely and usually are a result of a coding mistake. ## Cloning and merging, Object.assign @@ -547,7 +569,7 @@ for (let key in user) { // now clone is a fully independant clone clone.name = "Pete"; // changed the data in it -alert( user.name ); // still John +alert( user.name ); // still John in the original object ``` Also we can use the method [Object.assign](mdn:js/Object/assign) for that. @@ -558,12 +580,11 @@ The syntax is: Object.assign(dest[, src1, src2, src3...]) ``` -- `dest` and other arguments (can be as many as needed) are objects - -It copies the properties of all arguments starting from the 2nd (`src1`, `src2` etc) into the `dest`. Then it returns `dest`. +- Arguments `dest`, and `src1, ..., srcN` (can be as many as needed) are objects. +- It copies the properties of all objects `src1, ..., srcN` into `dest`. In other words, properties of all arguments starting from the 2nd are copied into the 1st. Then it returns `dest`. For instance, we can use it to merge several objects into one: -```js +```js let user = { name: "John" }; let permissions1 = { canView: true }; @@ -579,7 +600,7 @@ Object.assign(user, permissions1, permissions2); If the receiving object (`user`) already has the same named property, it will be overwritten: -```js +```js let user = { name: "John" }; // overwrite name, add isAdmin @@ -590,14 +611,14 @@ Object.assign(user, { name: "Pete", isAdmin: true }); We also can use `Object.assign` to replace the loop for simple cloning: -```js +```js let user = { name: "John", age: 30 }; *!* -let clone = Object.assign({}, user); +let clone = Object.assign({}, user); */!* ``` @@ -634,11 +655,12 @@ let clone = Object.assign({}, user); alert( user.sizes === clone.sizes ); // true, same object +// user and clone share sizes user.sizes.width++; // change a property from one place alert(clone.sizes.width); // 51, see the result from the other one ``` -To fix that, we should use the cloning loop that examines each value of `user[key]` and, if it's an object, then replicate it's structure as well. That is called a "deep cloning". +To fix that, we should use the cloning loop that examines each value of `user[key]` and, if it's an object, then replicate it's structure as well. That is called a "deep cloning". There's a standard algorithm for deep cloning that handles the case above and more complex cases, called the [Structured cloning algorithm](w3c.github.io/html/infrastructure.html#internal-structured-cloning-algorithm). Not to reinvent the wheel, we can use a working implementation of it from the Javascript library [lodash](https://lodash.com), the method is called [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep). @@ -667,9 +689,9 @@ Property access: - Integer properties in sorted order first, then strings in creation order, then symbols in creation order. - To keep the order for numeric properties, we can prepend them with `+` to make them look like non-numeric. -- Objects are assigned and copied by reference. +- Objects are assigned and copied by reference. -What we've just seen is called a "plain object", or just `Object`. +What we've just seen is called a "plain object", or just `Object`. There are many other kinds of objects in Javascript: @@ -681,4 +703,3 @@ There are many other kinds of objects in Javascript: Sometimes people say something like "Array type" or "Date type", but formally they are not types of their own, but belong to a single "object" data type. And they extend it in various ways. Objects in JavaScript are very powerful. Here we've just scratched the surface of the topic that is really huge. We'll be closely working with objects and learning more about them in further parts of the tutorial. - diff --git a/1-js/4-object-basics/02-garbage-collection/article.md b/1-js/4-object-basics/02-garbage-collection/article.md index 7a2e5f4e..39688522 100644 --- a/1-js/4-object-basics/02-garbage-collection/article.md +++ b/1-js/4-object-basics/02-garbage-collection/article.md @@ -8,11 +8,11 @@ What happens when something is not needed any more? How Javascript engine discov ## Reachability -The main concept of memory management in Javascript is *reachability*. +The main concept of memory management in Javascript is *reachability*. -Simply put, "reachable" values are those that are accessible now or in the future. They are guaranteed to be stored in memory. +Simply put, "reachable" values are those that are accessible or useable somehow. They are guaranteed to be stored in memory. -1. There's a base set of inherently reachable values, that cannot be deleted for obvious reasons. +1. There's a base set of inherently reachable values, that cannot be deleted for obvious reasons. For instance: @@ -21,11 +21,13 @@ Simply put, "reachable" values are those that are accessible now or in the futur - Global variables. - (there are some other, internal ones as well) - These values are called *roots*. + These values are called *roots*. -2. Any other value is retained in memory only while it's reachable from a root by a reference of by a chain of references. +2. Any other value is considered reachable if it's reachable from a root by a reference of by a chain of references. -There's a background process that runs by the engine itself called [garbage collector](https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)). It monitors all objects and removes those that became unreachable. + For instance, if there's an object in a local variable, and that object has a property referencing another object, that object is considered reachable. And those that it references -- are also reachable. Detailed examples to follow. + +There's a background process in the Javascript engine that is called [garbage collector](https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)). It monitors all objects and removes those that became unreachable. ## A simple example @@ -70,7 +72,7 @@ let admin = user; ![](memory-user-john-admin.png) Now if we do the same: -```js +```js user = null; ``` @@ -104,7 +106,7 @@ The resulting memory structure: ![](family.png) -As of now, all objects are reachable. +As of now, all objects are reachable. Now let's remove two references: @@ -143,7 +145,7 @@ The in-memory picture becomes: This example demonstrates how important the concept of reachability is. -It's obvious that John and Ann are still linked, both have incoming references. But that's not enough. +It's obvious that John and Ann are still linked, both have incoming references. But that's not enough. The former `"family"` object has been unlinked from the root, there's no reference to it any more, so the whole island becomes unreachable and will be removed. @@ -153,19 +155,19 @@ The basic garbage collection algorithm is called "mark-and-sweep". Regularly the following "garbage collection" steps are performed: -- The garbage collector takes roots and "marks" them. +- The garbage collector takes roots and "marks" (remembers) them. - Then it visits and "marks" all references from them. - Then it visits marked objects and marks *their* references. All visited objects are remembered, not to visit the same object twice in the future. - - ...And so on until there are unvisited references (reachable from the roots). - All objects except marked ones are removed. - -For instance, if our object structure looks like this: +For instance, let our object structure look like this: ![](garbage-collection-1.png) -Then the first step marks the roots: +We can clearly see an "unreachable island" to the right side. Now let's see how "mark-and-sweep" garbage collector deals with it. + +The first step marks the roots: ![](garbage-collection-2.png) @@ -183,15 +185,17 @@ Now the objects that could not be visited in the process are considered unreacha That's the concept how garbage collection works. -Javascript engines apply many optimizations to it, to make it run faster and be more hidden behind the scenes. +Javascript engines apply many optimizations to make it run faster and not affect the execution. Some of the optimizations: -- **Generational collection** -- objects are split into two sets: "new ones" and "old ones". Many objects appear, do their job and die fast, so they can be cleaned up more aggressively. Those "new" that survive for long enough, become "old". -- **Incremental collection** -- if there are many objects, and we try to walk and mark the whole object set at once, it may take some time and introduce visible delays. So the engine tries to split the job into pieces. Then pieces are executed one at a time. That requires some extra bookkeeping between them. +- **Generational collection** -- objects are split into two sets: "new ones" and "old ones". Many objects appear, then do their job and die fast, so they can be cleaned up aggressively. Those that survive for long enough, become "old". +- **Incremental collection** -- if there are many objects, and we try to walk and mark the whole object set at once, it may take some time and introduce visible delays in the execution. So the engine tries to split the job into pieces. Then pieces are executed one at a time. That requires some extra bookkeeping between them to track changes. - **Idle-time collection** -- the garbage collector tries to run only while the CPU is idle, to reduce the possible effect on the execution. -Detailed learning of these optimization is also possible, but it requires a lot of under-the-hood digging. Javascript engines implement garbage collection differently. And -- what's even more important, things change, so going really deep "in advance", without a real need is probably not worth that. Unless, of course, it is a matter of pure interest, then there will be some links for you below. +There are other optimizations and flavours of garbage collection algorithms. As much as I'd like to describe them here, I have to hold off, because different engines implement different tweaks and techniques. + +And -- what's even more important, things change as engines develop, so going really deep "in advance", without a real need is probably not worth that. Unless, of course, it is a matter of pure interest, then there will be some links for you below. ## Summary @@ -203,8 +207,10 @@ The main things to know: Modern engines implement advanced algorithms of garbage collection. -If you are familiar with low-level programming, the more detailed information about V8 garbage collector is in the article [A tour of V8: Garbage Collection](http://jayconrod.com/posts/55/a-tour-of-v8-garbage-collection), and [V8 blog](http://v8project.blogspot.com/) also publishes articles about changes in memory management from time to time. Also you'd better prepare yourself by learning about V8 in general and read the blog of [Vyacheslav Egorov](http://mrale.ph) who worked as one of V8 engineers. I'm saying: "V8", because it is best covered with articles in the internet. For other engines, many approaches are similar, but garbage collection differs in many aspects. +A general book "The Garbage Collection Handbook: The Art of Automatic Memory Management" (R. Jones at al) covers some of them. + +If you are familiar with low-level programming, the more detailed information about V8 garbage collector is in the article [A tour of V8: Garbage Collection](http://jayconrod.com/posts/55/a-tour-of-v8-garbage-collection). + +[V8 blog](http://v8project.blogspot.com/) also publishes articles about changes in memory management from time to time. Naturally, to learn the garbage collection, you'd better prepare by learning about V8 internals in general and read the blog of [Vyacheslav Egorov](http://mrale.ph) who worked as one of V8 engineers. I'm saying: "V8", because it is best covered with articles in the internet. For other engines, many approaches are similar, but garbage collection differs in many aspects. In-depth knowledge of engines is good when you need low-level optimizations. It would be wise to plan that as the next step after you're familiar with the language. - - diff --git a/1-js/4-object-basics/03-object-methods/8-chain-calls/_js.view/solution.js b/1-js/4-object-basics/03-object-methods/8-chain-calls/_js.view/solution.js new file mode 100644 index 00000000..e98fe641 --- /dev/null +++ b/1-js/4-object-basics/03-object-methods/8-chain-calls/_js.view/solution.js @@ -0,0 +1,15 @@ + +let ladder = { + step: 0, + up: function() { + this.step++; + return this; + }, + down: function() { + this.step--; + return this; + }, + showStep: function() { + alert(this.step); + } +}; \ No newline at end of file diff --git a/1-js/4-object-basics/03-object-methods/8-chain-calls/_js.view/test.js b/1-js/4-object-basics/03-object-methods/8-chain-calls/_js.view/test.js new file mode 100644 index 00000000..a2b17fcc --- /dev/null +++ b/1-js/4-object-basics/03-object-methods/8-chain-calls/_js.view/test.js @@ -0,0 +1,40 @@ + +describe('Ladder', function() { + before(function() { + window.alert = sinon.stub(window, "alert"); + }); + + beforeEach(function() { + ladder.step = 0; + }); + + it('up() should return this', function() { + assert.equal(ladder.up(), ladder); + }); + + it('down() should return this', function() { + assert.equal(ladder.down(), ladder); + }); + + it('showStep() should call alert', function() { + ladder.showStep(); + assert(alert.called); + }); + + it('up() should increase step', function() { + assert.equal(ladder.up().up().step, 2); + }); + + it('down() should decrease step', function() { + assert.equal(ladder.down().step, -1); + }); + + it('down().up().up().up() ', function() { + assert.equal(ladder.down().up().up().up().step, 2); + }); + + after(function() { + ladder.step = 0; + alert.restore(); + }); +}); diff --git a/1-js/4-object-basics/06-symbol/article.md b/1-js/4-object-basics/06-symbol/article.md index fc8c1b0b..fa1978d8 100644 --- a/1-js/4-object-basics/06-symbol/article.md +++ b/1-js/4-object-basics/06-symbol/article.md @@ -9,7 +9,7 @@ Till now we only saw strings. Now let's see the advantages that symbols can give ## Symbols -"Symbol" value represents an unique identifier with a given name. +"Symbol" value represents an unique identifier with a given name. A value of this type can be created using `Symbol(name)`: @@ -31,18 +31,18 @@ alert(id1 == id2); // false */!* ``` -If you are familiar with Ruby or another language that also has some sort of "symbols" -- please don't be misguided. Javascript symbols are different. +If you are familiar with Ruby or another language that also has some sort of "symbols" -- please don't be misguided. Javascript symbols are different. -## "Private" properties +## "Hidden" properties -Symbols allow to create concealed, "private" properties of an object, that no other part of code can occasionally access or overwrite. +Symbols allow to create "hidden" properties of an object, that no other part of code can occasionally access or overwrite. For instance, if we want to store an "identifier" for the object `user`, we can create a symbol with the name `id` for it: ```js run let user = { name: "John" }; -let id = Symbol("id"); +let id = Symbol("id"); user[id] = "ID Value"; alert( user[id] ); // we can access the data using the symbol as the key @@ -50,11 +50,11 @@ alert( user[id] ); // we can access the data using the symbol as the key Now let's imagine that another script wants to have his own "id" property inside `user`, for his own purposes. That may be another Javascript library, so the scripts are completely unaware for each other. -No problem. It can create its own `Symbol("id")`. +No problem. It can create its own `Symbol("id")`. Their script: -```js +```js // ... let id = Symbol("id"); @@ -77,7 +77,7 @@ user.id = "Their id value" // boom! overwritten! it did not mean to harm the colleague, but did it! ``` -### Symbols in literal +### Symbols in a literal If we want to use a symbol in an object literal, we need square brackets. @@ -93,9 +93,9 @@ let user = { */!* }; ``` -That's because we use the value from the variable `id`, not the string "id". +That's because we need the value from the variable `id` as the key, not the string "id". -### Symbols are not in loop +### Symbols skipped by for..in Symbolic properties do not participate in `for..in` loop. @@ -114,7 +114,7 @@ for(let key in user) alert(key); // name, age (no symbols) */!* // the direct access by the global symbol works -alert( "Direct: " + user[Symbol.for("id")] ); +alert( "Direct: " + user[Symbol.for("id")] ); ``` That's a part of the general "hiding" concept. If another script or a library loops over our object, it won't unexpectedly access a symbolic property. @@ -132,8 +132,7 @@ let clone = Object.assign({}, user); alert( clone[id] ); // 123 ``` -There's no paradox here. That's the expected behavior, because when we clone an object, we expect symbolic properties (like `id`) to be copied as well. - +There's no paradox here. That's by design. The idea is that when we clone an object or merge objects, we usually want symbolic properties (like `id`) to be copied as well. ````smart header="Property keys of other types are coerced to strings" We can only use strings or symbols as keys in objects. Other types are coerced to strings. @@ -155,7 +154,7 @@ alert( obj[0] ); // test (same property) Normally, all symbols are different. But sometimes we want same-named symbols to be the same. -For instance, different parts of our application want to access symbol `"id"` meaning the exactly the same property. +For instance, different parts of our application want to access symbol `"id"` meaning exactly the same property. To achieve that, there exists a *global symbol registry*. We can create symbols in it and and access them later, and it guarantees that repeated accesses by the same name return exactly the same symbol. @@ -177,7 +176,7 @@ alert( name === nameAgain ); // true Symbols inside the registry are called *global symbols*. If we want an application-wide symbol, accessible everywhere in the code -- that's what they are for. ```smart header="That sounds like Ruby" -In some programming languages, like Ruby, there's a single symbol per name. +In some programming languages, like Ruby, there's a single symbol per name. In Javascript, as we can see, that's right for global symbols. ``` @@ -221,7 +220,7 @@ They are listed in the specification in the [Well-known symbols](https://tc39.gi - `Symbol.toPrimitive` - ...and so on. -For instance, `Symbol.toPrimitive` allows to describe object to primitive conversion. We'll see its use very soon. +For instance, `Symbol.toPrimitive` allows to describe object to primitive conversion. We'll see its use very soon. Other symbols will also become familiar when we study the corresponding language features. @@ -229,11 +228,11 @@ Other symbols will also become familiar when we study the corresponding language - Symbol is a primitive type for unique identifiers. - Symbols are created with `Symbol(name)` call. -- Symbols are useful if we want to create a field that only those who know the symbol can access. +- Symbols are useful if we want to create a field that only those who know the symbol can access. - Symbols don't appear in `for..in` loops. - Symbols created with `Symbol(name)` are always different, even if they have the same name. If we want same-named symbols to be equal, then we should use the global registry: `Symbol.for(name)` returns (creates if needed) a global symbol with the given name. Multiple calls return the same symbol. - There are system symbols used by Javascript and accessible as `Symbol.*`. We can use them to alter some built-in behaviors. -Technically, symbols are not 100% hidden. There is a build-in method [Object.getOwnPropertySymbols(obj)](mdn:js/Object/getOwnPropertySymbols) that allows to get all symbols. Also there is a method named [Reflect.ownKeys(obj)](mdn:js/Reflect/ownKeys) that returns *all* keys of an object including symbolic ones. So they are not completely hidden and private. +Technically, symbols are not 100% hidden. There is a build-in method [Object.getOwnPropertySymbols(obj)](mdn:js/Object/getOwnPropertySymbols) that allows to get all symbols. Also there is a method named [Reflect.ownKeys(obj)](mdn:js/Reflect/ownKeys) that returns *all* keys of an object including symbolic ones. So they are not really hidden. -But most libraries, built-in methods and syntax constructs adhere to a common agreement that they are. And the one who explicitly calls the aforementioned methods probably understands well what he's doing. \ No newline at end of file +But most libraries, built-in methods and syntax constructs adhere to a common agreement that they are. And the one who explicitly calls the aforementioned methods probably understands well what he's doing. diff --git a/1-js/4-object-basics/07-object-toprimitive/article.md b/1-js/4-object-basics/07-object-toprimitive/article.md index 6324d689..ff36a530 100644 --- a/1-js/4-object-basics/07-object-toprimitive/article.md +++ b/1-js/4-object-basics/07-object-toprimitive/article.md @@ -5,7 +5,6 @@ In the chapter we've seen the rules for numeric, string But we left a gap for objects. Now let's fill it. - [cut] ## Where and why? @@ -16,18 +15,18 @@ The conversion of an object to primitive value (a number or a string) is a rare Just think about cases when such conversion may be necessary. For instance, numeric conversion happens when we compare an object against a primitive: `user > 18`. But what such comparison actually means? Are we going to compare `18` against user's age? Then it would be more obvious to write `user.age > 18`. And it's easier to read and understand it too. -Or, for a string conversion... Where does it happen? Usually, when we output an object. But simple ways of object-as-string output like `alert(user)` are only used for debugging and logging purposes. For real stuff, the output is more complicated, we may need to configure it with additional parameters. That's why it is usually implemented with object methods like `user.format()` or even in more advanced ways. +Or, for a string conversion... Where does it happen? Usually, when we output an object. But simple ways of object-as-string output like `alert(user)` are only used for debugging and logging purposes. For real stuff, the output is more complicated. That's why it is usually implemented with object methods like `user.format(...)` or even in more advanced ways. -So, most of the time, it's more flexible and gives more readable code to explicitly write an object property or call a method than rely on the conversion. +So, most of the time, it's more flexible and gives more readable code to explicitly get an object property or call a method than rely on the conversion. That said, there are still valid reasons why we should know how to-primitive conversion works. -- Simple object-as-string output may be useable sometimes. -- Many built-in objects implement their own to-primitive conversion, we plan to cover that. +- Simple object-as-string output is useable sometimes. +- Many built-in objects implement their own to-primitive conversion, we need to know how to work with that. - Sometimes an unexpected conversion happens, and we should understand what's going on. -- Okay, the final one. There are quizzes and questions on interviews that rely on that knowledge. Looks like people think it's a good sigh that person understands Javascript if he knows type conversions well. +- Okay, the final one. There are quizzes and questions on interviews that rely on that knowledge. Looks like people think it's a good sign that person understands Javascript if he knows type conversions well. -## ToPrimitive +## ToPrimitive The algorithm of object-to-primitive conversion is called `ToPrimitive` in [the specification](https://tc39.github.io/ecma262/#sec-toprimitive). @@ -39,9 +38,9 @@ There are 3 types (also called "hints") of object-to-primitive conversion: ```js // output alert(obj); - + // using object as a property key - anotherObj[obj] = value; + anotherObj[obj] = 123; ``` `"number"` @@ -52,15 +51,15 @@ There are 3 types (also called "hints") of object-to-primitive conversion: let num = Number(obj); // maths (except binary plus) - let n = +obj; // unary plus - let delta = date1 - date2; + let n = +obj; // unary plus + let delta = date1 - date2; // less/greater comparison let greater = user1 > user2; ``` `"default"` -: Occurs in rare cases where it's not clear what is desired. +: Occurs in rare cases where it's not clear what is desired. For instance: @@ -72,11 +71,11 @@ There are 3 types (also called "hints") of object-to-primitive conversion: if (user == 1) { ... }; ``` - There's some inconsistency here. The greater/less operator `<>` can work with both strings and numbers, it compares them differently. Still, it uses "number" hint. That's for historical reasons. + So, binary `+` and `==` use this hint. Seems right, because they operate both with strings and numbers. Although, there's some inconsistency here. The greater/less operator `<>` can work with both strings and numbers too. Still, it uses "number" hint. That's for historical reasons. In practice, all built-in objects except for one case (`Date` object, we'll learn it later) implement `"default"` conversion the same way as `"number"`. And probably we should do the same. -Please note -- there are only three conversions. That simple. There is no "boolean" (all objects are `true` in boolean context) or anything else. And if we treat `"default"` and `"number"` the same, like most built-ins do, then there are only two conversions. +Please note -- there are only three conversions. That simple. There is no "boolean" (all objects are `true` in boolean context) or anything else. And if we treat `"default"` and `"number"` the same, like most built-ins do, then there are only two conversions. To do the conversion, Javascript tries to find and call three object methods: @@ -84,7 +83,7 @@ To do the conversion, Javascript tries to find and call three object methods: 2. Otherwise if hint is `"string"`, try `toString()` and `valueOf()`, whatever exists. 3. Otherwise if hint is `"number"` or `"default"`, try `valueOf()` and `toString()`, whatever exists. -### Symbol.toPrimitive +## Symbol.toPrimitive For instance, here `user` object implements the 1st method: @@ -107,9 +106,9 @@ alert(user + 500); // hint: default -> 1500 As we can see from the code, `user` becomes a self-descriptive string or a money amount depending on the conversion. -### toString/valueOf +## toString/valueOf -Methods `toString` and `valueOf` come from ancient times. That's why they are not symbols. They provide an alternative "old-style" way to implement the conversion. +Methods `toString` and `valueOf` come from ancient times, that's why they are not symbols. They provide an alternative "old-style" way to implement the conversion. If there's no `Symbol.toPrimitive` then Javascript tries to find them and try in the order: @@ -166,16 +165,16 @@ There is no control whether `toString()` returns exactly a string, or whether `S **The only mandatory thing: these methods must return a primitive.** -An operation that initiated the conversion gets that primitive, and then continues to work with it, applying further conversions if necessary. +An operation that initiated the conversion gets that primitive, and then continues to work with it, applying further conversions if necessary. For instance: -- All mathematical operations except binary plus apply `ToNumber` after `ToPrimitive` with `"number"` hint: +- Mathematical operations (except binary plus) apply `ToNumber` after `ToPrimitive` with `"number"` hint: ```js run let obj = { toString() { // toString handles all ToPrimitive in the absense of other methods - return "2"; + return "2"; } }; @@ -187,8 +186,8 @@ For instance: String example: ```js run let obj = { - toString() { - return "2"; + toString() { + return "2"; } }; @@ -198,8 +197,8 @@ For instance: Number example: ```js run let obj = { - toString() { - return true; + toString() { + return true; } }; @@ -213,9 +212,6 @@ For instance: Minor notes: -- If `Symbol.toPrimitive` returns an object, that's an error. -- If `toString/valueOf` return an object, they are ignored (historical behavior). +- If `Symbol.toPrimitive` returns an object, that's an error. +- If `toString/valueOf` return an object, they are ignored (historical behavior). - By default, all objects have both `toString` and `valueOf`, but `valueOf` returns the object itself, and hence is ignored. - - - diff --git a/1-js/4-object-basics/04-primitives-methods/1-string-new-property/solution.md b/1-js/5-data-types/01-primitives-methods/1-string-new-property/solution.md similarity index 100% rename from 1-js/4-object-basics/04-primitives-methods/1-string-new-property/solution.md rename to 1-js/5-data-types/01-primitives-methods/1-string-new-property/solution.md diff --git a/1-js/4-object-basics/04-primitives-methods/1-string-new-property/task.md b/1-js/5-data-types/01-primitives-methods/1-string-new-property/task.md similarity index 100% rename from 1-js/4-object-basics/04-primitives-methods/1-string-new-property/task.md rename to 1-js/5-data-types/01-primitives-methods/1-string-new-property/task.md diff --git a/1-js/4-object-basics/04-primitives-methods/article.md b/1-js/5-data-types/01-primitives-methods/article.md similarity index 100% rename from 1-js/4-object-basics/04-primitives-methods/article.md rename to 1-js/5-data-types/01-primitives-methods/article.md diff --git a/1-js/5-data-types/01-number/1-sum-interface/solution.md b/1-js/5-data-types/02-number/1-sum-interface/solution.md similarity index 100% rename from 1-js/5-data-types/01-number/1-sum-interface/solution.md rename to 1-js/5-data-types/02-number/1-sum-interface/solution.md diff --git a/1-js/5-data-types/01-number/1-sum-interface/task.md b/1-js/5-data-types/02-number/1-sum-interface/task.md similarity index 100% rename from 1-js/5-data-types/01-number/1-sum-interface/task.md rename to 1-js/5-data-types/02-number/1-sum-interface/task.md diff --git a/1-js/5-data-types/01-number/2-why-rounded-down/solution.md b/1-js/5-data-types/02-number/2-why-rounded-down/solution.md similarity index 100% rename from 1-js/5-data-types/01-number/2-why-rounded-down/solution.md rename to 1-js/5-data-types/02-number/2-why-rounded-down/solution.md diff --git a/1-js/5-data-types/01-number/2-why-rounded-down/task.md b/1-js/5-data-types/02-number/2-why-rounded-down/task.md similarity index 100% rename from 1-js/5-data-types/01-number/2-why-rounded-down/task.md rename to 1-js/5-data-types/02-number/2-why-rounded-down/task.md diff --git a/1-js/5-data-types/01-number/3-repeat-until-number/_js.view/solution.js b/1-js/5-data-types/02-number/3-repeat-until-number/_js.view/solution.js similarity index 100% rename from 1-js/5-data-types/01-number/3-repeat-until-number/_js.view/solution.js rename to 1-js/5-data-types/02-number/3-repeat-until-number/_js.view/solution.js diff --git a/1-js/5-data-types/01-number/3-repeat-until-number/_js.view/test.js b/1-js/5-data-types/02-number/3-repeat-until-number/_js.view/test.js similarity index 100% rename from 1-js/5-data-types/01-number/3-repeat-until-number/_js.view/test.js rename to 1-js/5-data-types/02-number/3-repeat-until-number/_js.view/test.js diff --git a/1-js/5-data-types/01-number/3-repeat-until-number/solution.md b/1-js/5-data-types/02-number/3-repeat-until-number/solution.md similarity index 100% rename from 1-js/5-data-types/01-number/3-repeat-until-number/solution.md rename to 1-js/5-data-types/02-number/3-repeat-until-number/solution.md diff --git a/1-js/5-data-types/01-number/3-repeat-until-number/task.md b/1-js/5-data-types/02-number/3-repeat-until-number/task.md similarity index 100% rename from 1-js/5-data-types/01-number/3-repeat-until-number/task.md rename to 1-js/5-data-types/02-number/3-repeat-until-number/task.md diff --git a/1-js/5-data-types/01-number/4-endless-loop-error/solution.md b/1-js/5-data-types/02-number/4-endless-loop-error/solution.md similarity index 100% rename from 1-js/5-data-types/01-number/4-endless-loop-error/solution.md rename to 1-js/5-data-types/02-number/4-endless-loop-error/solution.md diff --git a/1-js/5-data-types/01-number/4-endless-loop-error/task.md b/1-js/5-data-types/02-number/4-endless-loop-error/task.md similarity index 100% rename from 1-js/5-data-types/01-number/4-endless-loop-error/task.md rename to 1-js/5-data-types/02-number/4-endless-loop-error/task.md diff --git a/1-js/5-data-types/01-number/8-random-min-max/solution.md b/1-js/5-data-types/02-number/8-random-min-max/solution.md similarity index 100% rename from 1-js/5-data-types/01-number/8-random-min-max/solution.md rename to 1-js/5-data-types/02-number/8-random-min-max/solution.md diff --git a/1-js/5-data-types/01-number/8-random-min-max/task.md b/1-js/5-data-types/02-number/8-random-min-max/task.md similarity index 100% rename from 1-js/5-data-types/01-number/8-random-min-max/task.md rename to 1-js/5-data-types/02-number/8-random-min-max/task.md diff --git a/1-js/5-data-types/01-number/9-random-int-min-max/solution.md b/1-js/5-data-types/02-number/9-random-int-min-max/solution.md similarity index 100% rename from 1-js/5-data-types/01-number/9-random-int-min-max/solution.md rename to 1-js/5-data-types/02-number/9-random-int-min-max/solution.md diff --git a/1-js/5-data-types/01-number/9-random-int-min-max/task.md b/1-js/5-data-types/02-number/9-random-int-min-max/task.md similarity index 100% rename from 1-js/5-data-types/01-number/9-random-int-min-max/task.md rename to 1-js/5-data-types/02-number/9-random-int-min-max/task.md diff --git a/1-js/5-data-types/01-number/article.md b/1-js/5-data-types/02-number/article.md similarity index 100% rename from 1-js/5-data-types/01-number/article.md rename to 1-js/5-data-types/02-number/article.md diff --git a/1-js/5-data-types/02-string/1-ucfirst/_js.view/solution.js b/1-js/5-data-types/03-string/1-ucfirst/_js.view/solution.js similarity index 100% rename from 1-js/5-data-types/02-string/1-ucfirst/_js.view/solution.js rename to 1-js/5-data-types/03-string/1-ucfirst/_js.view/solution.js diff --git a/1-js/5-data-types/02-string/1-ucfirst/_js.view/test.js b/1-js/5-data-types/03-string/1-ucfirst/_js.view/test.js similarity index 100% rename from 1-js/5-data-types/02-string/1-ucfirst/_js.view/test.js rename to 1-js/5-data-types/03-string/1-ucfirst/_js.view/test.js diff --git a/1-js/5-data-types/02-string/1-ucfirst/solution.md b/1-js/5-data-types/03-string/1-ucfirst/solution.md similarity index 100% rename from 1-js/5-data-types/02-string/1-ucfirst/solution.md rename to 1-js/5-data-types/03-string/1-ucfirst/solution.md diff --git a/1-js/5-data-types/02-string/1-ucfirst/task.md b/1-js/5-data-types/03-string/1-ucfirst/task.md similarity index 100% rename from 1-js/5-data-types/02-string/1-ucfirst/task.md rename to 1-js/5-data-types/03-string/1-ucfirst/task.md diff --git a/1-js/5-data-types/02-string/2-check-spam/_js.view/solution.js b/1-js/5-data-types/03-string/2-check-spam/_js.view/solution.js similarity index 100% rename from 1-js/5-data-types/02-string/2-check-spam/_js.view/solution.js rename to 1-js/5-data-types/03-string/2-check-spam/_js.view/solution.js diff --git a/1-js/5-data-types/02-string/2-check-spam/_js.view/test.js b/1-js/5-data-types/03-string/2-check-spam/_js.view/test.js similarity index 100% rename from 1-js/5-data-types/02-string/2-check-spam/_js.view/test.js rename to 1-js/5-data-types/03-string/2-check-spam/_js.view/test.js diff --git a/1-js/5-data-types/02-string/2-check-spam/solution.md b/1-js/5-data-types/03-string/2-check-spam/solution.md similarity index 100% rename from 1-js/5-data-types/02-string/2-check-spam/solution.md rename to 1-js/5-data-types/03-string/2-check-spam/solution.md diff --git a/1-js/5-data-types/02-string/2-check-spam/task.md b/1-js/5-data-types/03-string/2-check-spam/task.md similarity index 100% rename from 1-js/5-data-types/02-string/2-check-spam/task.md rename to 1-js/5-data-types/03-string/2-check-spam/task.md diff --git a/1-js/5-data-types/02-string/3-truncate/_js.view/solution.js b/1-js/5-data-types/03-string/3-truncate/_js.view/solution.js similarity index 100% rename from 1-js/5-data-types/02-string/3-truncate/_js.view/solution.js rename to 1-js/5-data-types/03-string/3-truncate/_js.view/solution.js diff --git a/1-js/5-data-types/02-string/3-truncate/_js.view/test.js b/1-js/5-data-types/03-string/3-truncate/_js.view/test.js similarity index 100% rename from 1-js/5-data-types/02-string/3-truncate/_js.view/test.js rename to 1-js/5-data-types/03-string/3-truncate/_js.view/test.js diff --git a/1-js/5-data-types/02-string/3-truncate/solution.md b/1-js/5-data-types/03-string/3-truncate/solution.md similarity index 100% rename from 1-js/5-data-types/02-string/3-truncate/solution.md rename to 1-js/5-data-types/03-string/3-truncate/solution.md diff --git a/1-js/5-data-types/02-string/3-truncate/task.md b/1-js/5-data-types/03-string/3-truncate/task.md similarity index 100% rename from 1-js/5-data-types/02-string/3-truncate/task.md rename to 1-js/5-data-types/03-string/3-truncate/task.md diff --git a/1-js/5-data-types/02-string/4-extract-currency/_js.view/solution.js b/1-js/5-data-types/03-string/4-extract-currency/_js.view/solution.js similarity index 100% rename from 1-js/5-data-types/02-string/4-extract-currency/_js.view/solution.js rename to 1-js/5-data-types/03-string/4-extract-currency/_js.view/solution.js diff --git a/1-js/5-data-types/02-string/4-extract-currency/_js.view/test.js b/1-js/5-data-types/03-string/4-extract-currency/_js.view/test.js similarity index 100% rename from 1-js/5-data-types/02-string/4-extract-currency/_js.view/test.js rename to 1-js/5-data-types/03-string/4-extract-currency/_js.view/test.js diff --git a/1-js/5-data-types/02-string/4-extract-currency/solution.md b/1-js/5-data-types/03-string/4-extract-currency/solution.md similarity index 100% rename from 1-js/5-data-types/02-string/4-extract-currency/solution.md rename to 1-js/5-data-types/03-string/4-extract-currency/solution.md diff --git a/1-js/5-data-types/02-string/4-extract-currency/task.md b/1-js/5-data-types/03-string/4-extract-currency/task.md similarity index 100% rename from 1-js/5-data-types/02-string/4-extract-currency/task.md rename to 1-js/5-data-types/03-string/4-extract-currency/task.md diff --git a/1-js/5-data-types/02-string/article.md b/1-js/5-data-types/03-string/article.md similarity index 100% rename from 1-js/5-data-types/02-string/article.md rename to 1-js/5-data-types/03-string/article.md diff --git a/1-js/5-data-types/03-date/1-new-date/solution.md b/1-js/5-data-types/04-date/1-new-date/solution.md similarity index 100% rename from 1-js/5-data-types/03-date/1-new-date/solution.md rename to 1-js/5-data-types/04-date/1-new-date/solution.md diff --git a/1-js/5-data-types/03-date/1-new-date/task.md b/1-js/5-data-types/04-date/1-new-date/task.md similarity index 100% rename from 1-js/5-data-types/03-date/1-new-date/task.md rename to 1-js/5-data-types/04-date/1-new-date/task.md diff --git a/1-js/5-data-types/03-date/2-get-week-day/_js.view/solution.js b/1-js/5-data-types/04-date/2-get-week-day/_js.view/solution.js similarity index 100% rename from 1-js/5-data-types/03-date/2-get-week-day/_js.view/solution.js rename to 1-js/5-data-types/04-date/2-get-week-day/_js.view/solution.js diff --git a/1-js/5-data-types/03-date/2-get-week-day/_js.view/test.js b/1-js/5-data-types/04-date/2-get-week-day/_js.view/test.js similarity index 100% rename from 1-js/5-data-types/03-date/2-get-week-day/_js.view/test.js rename to 1-js/5-data-types/04-date/2-get-week-day/_js.view/test.js diff --git a/1-js/5-data-types/03-date/2-get-week-day/solution.md b/1-js/5-data-types/04-date/2-get-week-day/solution.md similarity index 100% rename from 1-js/5-data-types/03-date/2-get-week-day/solution.md rename to 1-js/5-data-types/04-date/2-get-week-day/solution.md diff --git a/1-js/5-data-types/03-date/2-get-week-day/task.md b/1-js/5-data-types/04-date/2-get-week-day/task.md similarity index 100% rename from 1-js/5-data-types/03-date/2-get-week-day/task.md rename to 1-js/5-data-types/04-date/2-get-week-day/task.md diff --git a/1-js/5-data-types/03-date/3-weekday/_js.view/solution.js b/1-js/5-data-types/04-date/3-weekday/_js.view/solution.js similarity index 100% rename from 1-js/5-data-types/03-date/3-weekday/_js.view/solution.js rename to 1-js/5-data-types/04-date/3-weekday/_js.view/solution.js diff --git a/1-js/5-data-types/03-date/3-weekday/_js.view/test.js b/1-js/5-data-types/04-date/3-weekday/_js.view/test.js similarity index 100% rename from 1-js/5-data-types/03-date/3-weekday/_js.view/test.js rename to 1-js/5-data-types/04-date/3-weekday/_js.view/test.js diff --git a/1-js/5-data-types/03-date/3-weekday/solution.md b/1-js/5-data-types/04-date/3-weekday/solution.md similarity index 100% rename from 1-js/5-data-types/03-date/3-weekday/solution.md rename to 1-js/5-data-types/04-date/3-weekday/solution.md diff --git a/1-js/5-data-types/03-date/3-weekday/task.md b/1-js/5-data-types/04-date/3-weekday/task.md similarity index 100% rename from 1-js/5-data-types/03-date/3-weekday/task.md rename to 1-js/5-data-types/04-date/3-weekday/task.md diff --git a/1-js/5-data-types/03-date/4-get-date-ago/_js.view/solution.js b/1-js/5-data-types/04-date/4-get-date-ago/_js.view/solution.js similarity index 100% rename from 1-js/5-data-types/03-date/4-get-date-ago/_js.view/solution.js rename to 1-js/5-data-types/04-date/4-get-date-ago/_js.view/solution.js diff --git a/1-js/5-data-types/03-date/4-get-date-ago/_js.view/test.js b/1-js/5-data-types/04-date/4-get-date-ago/_js.view/test.js similarity index 100% rename from 1-js/5-data-types/03-date/4-get-date-ago/_js.view/test.js rename to 1-js/5-data-types/04-date/4-get-date-ago/_js.view/test.js diff --git a/1-js/5-data-types/03-date/4-get-date-ago/solution.md b/1-js/5-data-types/04-date/4-get-date-ago/solution.md similarity index 100% rename from 1-js/5-data-types/03-date/4-get-date-ago/solution.md rename to 1-js/5-data-types/04-date/4-get-date-ago/solution.md diff --git a/1-js/5-data-types/03-date/4-get-date-ago/task.md b/1-js/5-data-types/04-date/4-get-date-ago/task.md similarity index 100% rename from 1-js/5-data-types/03-date/4-get-date-ago/task.md rename to 1-js/5-data-types/04-date/4-get-date-ago/task.md diff --git a/1-js/5-data-types/03-date/5-last-day-of-month/_js.view/solution.js b/1-js/5-data-types/04-date/5-last-day-of-month/_js.view/solution.js similarity index 100% rename from 1-js/5-data-types/03-date/5-last-day-of-month/_js.view/solution.js rename to 1-js/5-data-types/04-date/5-last-day-of-month/_js.view/solution.js diff --git a/1-js/5-data-types/03-date/5-last-day-of-month/_js.view/test.js b/1-js/5-data-types/04-date/5-last-day-of-month/_js.view/test.js similarity index 100% rename from 1-js/5-data-types/03-date/5-last-day-of-month/_js.view/test.js rename to 1-js/5-data-types/04-date/5-last-day-of-month/_js.view/test.js diff --git a/1-js/5-data-types/03-date/5-last-day-of-month/solution.md b/1-js/5-data-types/04-date/5-last-day-of-month/solution.md similarity index 100% rename from 1-js/5-data-types/03-date/5-last-day-of-month/solution.md rename to 1-js/5-data-types/04-date/5-last-day-of-month/solution.md diff --git a/1-js/5-data-types/03-date/5-last-day-of-month/task.md b/1-js/5-data-types/04-date/5-last-day-of-month/task.md similarity index 100% rename from 1-js/5-data-types/03-date/5-last-day-of-month/task.md rename to 1-js/5-data-types/04-date/5-last-day-of-month/task.md diff --git a/1-js/5-data-types/03-date/6-get-seconds-today/solution.md b/1-js/5-data-types/04-date/6-get-seconds-today/solution.md similarity index 100% rename from 1-js/5-data-types/03-date/6-get-seconds-today/solution.md rename to 1-js/5-data-types/04-date/6-get-seconds-today/solution.md diff --git a/1-js/5-data-types/03-date/6-get-seconds-today/task.md b/1-js/5-data-types/04-date/6-get-seconds-today/task.md similarity index 100% rename from 1-js/5-data-types/03-date/6-get-seconds-today/task.md rename to 1-js/5-data-types/04-date/6-get-seconds-today/task.md diff --git a/1-js/5-data-types/03-date/7-get-seconds-to-tomorrow/solution.md b/1-js/5-data-types/04-date/7-get-seconds-to-tomorrow/solution.md similarity index 100% rename from 1-js/5-data-types/03-date/7-get-seconds-to-tomorrow/solution.md rename to 1-js/5-data-types/04-date/7-get-seconds-to-tomorrow/solution.md diff --git a/1-js/5-data-types/03-date/7-get-seconds-to-tomorrow/task.md b/1-js/5-data-types/04-date/7-get-seconds-to-tomorrow/task.md similarity index 100% rename from 1-js/5-data-types/03-date/7-get-seconds-to-tomorrow/task.md rename to 1-js/5-data-types/04-date/7-get-seconds-to-tomorrow/task.md diff --git a/1-js/5-data-types/03-date/8-format-date-relative/_js.view/solution.js b/1-js/5-data-types/04-date/8-format-date-relative/_js.view/solution.js similarity index 100% rename from 1-js/5-data-types/03-date/8-format-date-relative/_js.view/solution.js rename to 1-js/5-data-types/04-date/8-format-date-relative/_js.view/solution.js diff --git a/1-js/5-data-types/03-date/8-format-date-relative/_js.view/test.js b/1-js/5-data-types/04-date/8-format-date-relative/_js.view/test.js similarity index 100% rename from 1-js/5-data-types/03-date/8-format-date-relative/_js.view/test.js rename to 1-js/5-data-types/04-date/8-format-date-relative/_js.view/test.js diff --git a/1-js/5-data-types/03-date/8-format-date-relative/solution.md b/1-js/5-data-types/04-date/8-format-date-relative/solution.md similarity index 100% rename from 1-js/5-data-types/03-date/8-format-date-relative/solution.md rename to 1-js/5-data-types/04-date/8-format-date-relative/solution.md diff --git a/1-js/5-data-types/03-date/8-format-date-relative/task.md b/1-js/5-data-types/04-date/8-format-date-relative/task.md similarity index 100% rename from 1-js/5-data-types/03-date/8-format-date-relative/task.md rename to 1-js/5-data-types/04-date/8-format-date-relative/task.md diff --git a/1-js/5-data-types/03-date/article.md b/1-js/5-data-types/04-date/article.md similarity index 100% rename from 1-js/5-data-types/03-date/article.md rename to 1-js/5-data-types/04-date/article.md diff --git a/1-js/5-data-types/04-array/1-item-value/solution.md b/1-js/5-data-types/05-array/1-item-value/solution.md similarity index 100% rename from 1-js/5-data-types/04-array/1-item-value/solution.md rename to 1-js/5-data-types/05-array/1-item-value/solution.md diff --git a/1-js/5-data-types/04-array/1-item-value/task.md b/1-js/5-data-types/05-array/1-item-value/task.md similarity index 100% rename from 1-js/5-data-types/04-array/1-item-value/task.md rename to 1-js/5-data-types/05-array/1-item-value/task.md diff --git a/1-js/5-data-types/04-array/10-maximal-subarray/_js.view/solution.js b/1-js/5-data-types/05-array/10-maximal-subarray/_js.view/solution.js similarity index 100% rename from 1-js/5-data-types/04-array/10-maximal-subarray/_js.view/solution.js rename to 1-js/5-data-types/05-array/10-maximal-subarray/_js.view/solution.js diff --git a/1-js/5-data-types/04-array/10-maximal-subarray/_js.view/test.js b/1-js/5-data-types/05-array/10-maximal-subarray/_js.view/test.js similarity index 100% rename from 1-js/5-data-types/04-array/10-maximal-subarray/_js.view/test.js rename to 1-js/5-data-types/05-array/10-maximal-subarray/_js.view/test.js diff --git a/1-js/5-data-types/04-array/10-maximal-subarray/solution.md b/1-js/5-data-types/05-array/10-maximal-subarray/solution.md similarity index 100% rename from 1-js/5-data-types/04-array/10-maximal-subarray/solution.md rename to 1-js/5-data-types/05-array/10-maximal-subarray/solution.md diff --git a/1-js/5-data-types/04-array/10-maximal-subarray/task.md b/1-js/5-data-types/05-array/10-maximal-subarray/task.md similarity index 100% rename from 1-js/5-data-types/04-array/10-maximal-subarray/task.md rename to 1-js/5-data-types/05-array/10-maximal-subarray/task.md diff --git a/1-js/5-data-types/04-array/2-create-array/solution.md b/1-js/5-data-types/05-array/2-create-array/solution.md similarity index 100% rename from 1-js/5-data-types/04-array/2-create-array/solution.md rename to 1-js/5-data-types/05-array/2-create-array/solution.md diff --git a/1-js/5-data-types/04-array/2-create-array/task.md b/1-js/5-data-types/05-array/2-create-array/task.md similarity index 100% rename from 1-js/5-data-types/04-array/2-create-array/task.md rename to 1-js/5-data-types/05-array/2-create-array/task.md diff --git a/1-js/5-data-types/04-array/3-call-array-this/solution.md b/1-js/5-data-types/05-array/3-call-array-this/solution.md similarity index 100% rename from 1-js/5-data-types/04-array/3-call-array-this/solution.md rename to 1-js/5-data-types/05-array/3-call-array-this/solution.md diff --git a/1-js/5-data-types/04-array/3-call-array-this/task.md b/1-js/5-data-types/05-array/3-call-array-this/task.md similarity index 100% rename from 1-js/5-data-types/04-array/3-call-array-this/task.md rename to 1-js/5-data-types/05-array/3-call-array-this/task.md diff --git a/1-js/5-data-types/04-array/5-array-input-sum/solution.md b/1-js/5-data-types/05-array/5-array-input-sum/solution.md similarity index 100% rename from 1-js/5-data-types/04-array/5-array-input-sum/solution.md rename to 1-js/5-data-types/05-array/5-array-input-sum/solution.md diff --git a/1-js/5-data-types/04-array/5-array-input-sum/task.md b/1-js/5-data-types/05-array/5-array-input-sum/task.md similarity index 100% rename from 1-js/5-data-types/04-array/5-array-input-sum/task.md rename to 1-js/5-data-types/05-array/5-array-input-sum/task.md diff --git a/1-js/5-data-types/04-array/array-pop.png b/1-js/5-data-types/05-array/array-pop.png similarity index 100% rename from 1-js/5-data-types/04-array/array-pop.png rename to 1-js/5-data-types/05-array/array-pop.png diff --git a/1-js/5-data-types/04-array/array-pop@2x.png b/1-js/5-data-types/05-array/array-pop@2x.png similarity index 100% rename from 1-js/5-data-types/04-array/array-pop@2x.png rename to 1-js/5-data-types/05-array/array-pop@2x.png diff --git a/1-js/5-data-types/04-array/array-shift.png b/1-js/5-data-types/05-array/array-shift.png similarity index 100% rename from 1-js/5-data-types/04-array/array-shift.png rename to 1-js/5-data-types/05-array/array-shift.png diff --git a/1-js/5-data-types/04-array/array-shift@2x.png b/1-js/5-data-types/05-array/array-shift@2x.png similarity index 100% rename from 1-js/5-data-types/04-array/array-shift@2x.png rename to 1-js/5-data-types/05-array/array-shift@2x.png diff --git a/1-js/5-data-types/04-array/array-speed.png b/1-js/5-data-types/05-array/array-speed.png similarity index 100% rename from 1-js/5-data-types/04-array/array-speed.png rename to 1-js/5-data-types/05-array/array-speed.png diff --git a/1-js/5-data-types/04-array/array-speed@2x.png b/1-js/5-data-types/05-array/array-speed@2x.png similarity index 100% rename from 1-js/5-data-types/04-array/array-speed@2x.png rename to 1-js/5-data-types/05-array/array-speed@2x.png diff --git a/1-js/5-data-types/04-array/article.md b/1-js/5-data-types/05-array/article.md similarity index 100% rename from 1-js/5-data-types/04-array/article.md rename to 1-js/5-data-types/05-array/article.md diff --git a/1-js/5-data-types/04-array/queue.png b/1-js/5-data-types/05-array/queue.png similarity index 100% rename from 1-js/5-data-types/04-array/queue.png rename to 1-js/5-data-types/05-array/queue.png diff --git a/1-js/5-data-types/04-array/queue@2x.png b/1-js/5-data-types/05-array/queue@2x.png similarity index 100% rename from 1-js/5-data-types/04-array/queue@2x.png rename to 1-js/5-data-types/05-array/queue@2x.png diff --git a/1-js/5-data-types/04-array/stack.png b/1-js/5-data-types/05-array/stack.png similarity index 100% rename from 1-js/5-data-types/04-array/stack.png rename to 1-js/5-data-types/05-array/stack.png diff --git a/1-js/5-data-types/04-array/stack@2x.png b/1-js/5-data-types/05-array/stack@2x.png similarity index 100% rename from 1-js/5-data-types/04-array/stack@2x.png rename to 1-js/5-data-types/05-array/stack@2x.png diff --git a/1-js/5-data-types/05-array-methods/1-camelcase/_js.view/solution.js b/1-js/5-data-types/06-array-methods/1-camelcase/_js.view/solution.js similarity index 100% rename from 1-js/5-data-types/05-array-methods/1-camelcase/_js.view/solution.js rename to 1-js/5-data-types/06-array-methods/1-camelcase/_js.view/solution.js diff --git a/1-js/5-data-types/05-array-methods/1-camelcase/_js.view/test.js b/1-js/5-data-types/06-array-methods/1-camelcase/_js.view/test.js similarity index 100% rename from 1-js/5-data-types/05-array-methods/1-camelcase/_js.view/test.js rename to 1-js/5-data-types/06-array-methods/1-camelcase/_js.view/test.js diff --git a/1-js/5-data-types/05-array-methods/1-camelcase/solution.md b/1-js/5-data-types/06-array-methods/1-camelcase/solution.md similarity index 100% rename from 1-js/5-data-types/05-array-methods/1-camelcase/solution.md rename to 1-js/5-data-types/06-array-methods/1-camelcase/solution.md diff --git a/1-js/5-data-types/05-array-methods/1-camelcase/task.md b/1-js/5-data-types/06-array-methods/1-camelcase/task.md similarity index 100% rename from 1-js/5-data-types/05-array-methods/1-camelcase/task.md rename to 1-js/5-data-types/06-array-methods/1-camelcase/task.md diff --git a/1-js/5-data-types/05-array-methods/11-array-unique/_js.view/solution.js b/1-js/5-data-types/06-array-methods/11-array-unique/_js.view/solution.js similarity index 100% rename from 1-js/5-data-types/05-array-methods/11-array-unique/_js.view/solution.js rename to 1-js/5-data-types/06-array-methods/11-array-unique/_js.view/solution.js diff --git a/1-js/5-data-types/05-array-methods/11-array-unique/_js.view/test.js b/1-js/5-data-types/06-array-methods/11-array-unique/_js.view/test.js similarity index 100% rename from 1-js/5-data-types/05-array-methods/11-array-unique/_js.view/test.js rename to 1-js/5-data-types/06-array-methods/11-array-unique/_js.view/test.js diff --git a/1-js/5-data-types/05-array-methods/11-array-unique/solution.md b/1-js/5-data-types/06-array-methods/11-array-unique/solution.md similarity index 100% rename from 1-js/5-data-types/05-array-methods/11-array-unique/solution.md rename to 1-js/5-data-types/06-array-methods/11-array-unique/solution.md diff --git a/1-js/5-data-types/05-array-methods/11-array-unique/task.md b/1-js/5-data-types/06-array-methods/11-array-unique/task.md similarity index 100% rename from 1-js/5-data-types/05-array-methods/11-array-unique/task.md rename to 1-js/5-data-types/06-array-methods/11-array-unique/task.md diff --git a/1-js/5-data-types/05-array-methods/2-filter-range/_js.view/solution.js b/1-js/5-data-types/06-array-methods/2-filter-range/_js.view/solution.js similarity index 100% rename from 1-js/5-data-types/05-array-methods/2-filter-range/_js.view/solution.js rename to 1-js/5-data-types/06-array-methods/2-filter-range/_js.view/solution.js diff --git a/1-js/5-data-types/05-array-methods/2-filter-range/_js.view/test.js b/1-js/5-data-types/06-array-methods/2-filter-range/_js.view/test.js similarity index 100% rename from 1-js/5-data-types/05-array-methods/2-filter-range/_js.view/test.js rename to 1-js/5-data-types/06-array-methods/2-filter-range/_js.view/test.js diff --git a/1-js/5-data-types/05-array-methods/2-filter-range/solution.md b/1-js/5-data-types/06-array-methods/2-filter-range/solution.md similarity index 100% rename from 1-js/5-data-types/05-array-methods/2-filter-range/solution.md rename to 1-js/5-data-types/06-array-methods/2-filter-range/solution.md diff --git a/1-js/5-data-types/05-array-methods/2-filter-range/task.md b/1-js/5-data-types/06-array-methods/2-filter-range/task.md similarity index 100% rename from 1-js/5-data-types/05-array-methods/2-filter-range/task.md rename to 1-js/5-data-types/06-array-methods/2-filter-range/task.md diff --git a/1-js/5-data-types/05-array-methods/3-filter-range-in-place/_js.view/solution.js b/1-js/5-data-types/06-array-methods/3-filter-range-in-place/_js.view/solution.js similarity index 100% rename from 1-js/5-data-types/05-array-methods/3-filter-range-in-place/_js.view/solution.js rename to 1-js/5-data-types/06-array-methods/3-filter-range-in-place/_js.view/solution.js diff --git a/1-js/5-data-types/05-array-methods/3-filter-range-in-place/_js.view/test.js b/1-js/5-data-types/06-array-methods/3-filter-range-in-place/_js.view/test.js similarity index 100% rename from 1-js/5-data-types/05-array-methods/3-filter-range-in-place/_js.view/test.js rename to 1-js/5-data-types/06-array-methods/3-filter-range-in-place/_js.view/test.js diff --git a/1-js/5-data-types/05-array-methods/3-filter-range-in-place/solution.md b/1-js/5-data-types/06-array-methods/3-filter-range-in-place/solution.md similarity index 100% rename from 1-js/5-data-types/05-array-methods/3-filter-range-in-place/solution.md rename to 1-js/5-data-types/06-array-methods/3-filter-range-in-place/solution.md diff --git a/1-js/5-data-types/05-array-methods/3-filter-range-in-place/task.md b/1-js/5-data-types/06-array-methods/3-filter-range-in-place/task.md similarity index 100% rename from 1-js/5-data-types/05-array-methods/3-filter-range-in-place/task.md rename to 1-js/5-data-types/06-array-methods/3-filter-range-in-place/task.md diff --git a/1-js/5-data-types/05-array-methods/4-sort-back/solution.md b/1-js/5-data-types/06-array-methods/4-sort-back/solution.md similarity index 100% rename from 1-js/5-data-types/05-array-methods/4-sort-back/solution.md rename to 1-js/5-data-types/06-array-methods/4-sort-back/solution.md diff --git a/1-js/5-data-types/05-array-methods/4-sort-back/task.md b/1-js/5-data-types/06-array-methods/4-sort-back/task.md similarity index 100% rename from 1-js/5-data-types/05-array-methods/4-sort-back/task.md rename to 1-js/5-data-types/06-array-methods/4-sort-back/task.md diff --git a/1-js/5-data-types/05-array-methods/5-copy-sort-array/solution.md b/1-js/5-data-types/06-array-methods/5-copy-sort-array/solution.md similarity index 100% rename from 1-js/5-data-types/05-array-methods/5-copy-sort-array/solution.md rename to 1-js/5-data-types/06-array-methods/5-copy-sort-array/solution.md diff --git a/1-js/5-data-types/05-array-methods/5-copy-sort-array/task.md b/1-js/5-data-types/06-array-methods/5-copy-sort-array/task.md similarity index 100% rename from 1-js/5-data-types/05-array-methods/5-copy-sort-array/task.md rename to 1-js/5-data-types/06-array-methods/5-copy-sort-array/task.md diff --git a/1-js/5-data-types/05-array-methods/6-array-get-names/solution.md b/1-js/5-data-types/06-array-methods/6-array-get-names/solution.md similarity index 100% rename from 1-js/5-data-types/05-array-methods/6-array-get-names/solution.md rename to 1-js/5-data-types/06-array-methods/6-array-get-names/solution.md diff --git a/1-js/5-data-types/05-array-methods/6-array-get-names/task.md b/1-js/5-data-types/06-array-methods/6-array-get-names/task.md similarity index 100% rename from 1-js/5-data-types/05-array-methods/6-array-get-names/task.md rename to 1-js/5-data-types/06-array-methods/6-array-get-names/task.md diff --git a/1-js/5-data-types/05-array-methods/7-map-objects/solution.md b/1-js/5-data-types/06-array-methods/7-map-objects/solution.md similarity index 100% rename from 1-js/5-data-types/05-array-methods/7-map-objects/solution.md rename to 1-js/5-data-types/06-array-methods/7-map-objects/solution.md diff --git a/1-js/5-data-types/05-array-methods/7-map-objects/task.md b/1-js/5-data-types/06-array-methods/7-map-objects/task.md similarity index 100% rename from 1-js/5-data-types/05-array-methods/7-map-objects/task.md rename to 1-js/5-data-types/06-array-methods/7-map-objects/task.md diff --git a/1-js/5-data-types/05-array-methods/8-sort-objects/solution.md b/1-js/5-data-types/06-array-methods/8-sort-objects/solution.md similarity index 100% rename from 1-js/5-data-types/05-array-methods/8-sort-objects/solution.md rename to 1-js/5-data-types/06-array-methods/8-sort-objects/solution.md diff --git a/1-js/5-data-types/05-array-methods/8-sort-objects/task.md b/1-js/5-data-types/06-array-methods/8-sort-objects/task.md similarity index 100% rename from 1-js/5-data-types/05-array-methods/8-sort-objects/task.md rename to 1-js/5-data-types/06-array-methods/8-sort-objects/task.md diff --git a/1-js/5-data-types/05-array-methods/9-average-age/solution.md b/1-js/5-data-types/06-array-methods/9-average-age/solution.md similarity index 100% rename from 1-js/5-data-types/05-array-methods/9-average-age/solution.md rename to 1-js/5-data-types/06-array-methods/9-average-age/solution.md diff --git a/1-js/5-data-types/05-array-methods/9-average-age/task.md b/1-js/5-data-types/06-array-methods/9-average-age/task.md similarity index 100% rename from 1-js/5-data-types/05-array-methods/9-average-age/task.md rename to 1-js/5-data-types/06-array-methods/9-average-age/task.md diff --git a/1-js/5-data-types/05-array-methods/article.md b/1-js/5-data-types/06-array-methods/article.md similarity index 100% rename from 1-js/5-data-types/05-array-methods/article.md rename to 1-js/5-data-types/06-array-methods/article.md diff --git a/1-js/5-data-types/05-array-methods/reduce.png b/1-js/5-data-types/06-array-methods/reduce.png similarity index 100% rename from 1-js/5-data-types/05-array-methods/reduce.png rename to 1-js/5-data-types/06-array-methods/reduce.png diff --git a/1-js/5-data-types/05-array-methods/reduce@2x.png b/1-js/5-data-types/06-array-methods/reduce@2x.png similarity index 100% rename from 1-js/5-data-types/05-array-methods/reduce@2x.png rename to 1-js/5-data-types/06-array-methods/reduce@2x.png diff --git a/1-js/5-data-types/06-iterable/article.md b/1-js/5-data-types/07-iterable/article.md similarity index 100% rename from 1-js/5-data-types/06-iterable/article.md rename to 1-js/5-data-types/07-iterable/article.md diff --git a/1-js/5-data-types/07-map-set-weakmap-weakset/1-filter-anagrams/_js.view/solution.js b/1-js/5-data-types/08-map-set-weakmap-weakset/1-filter-anagrams/_js.view/solution.js similarity index 100% rename from 1-js/5-data-types/07-map-set-weakmap-weakset/1-filter-anagrams/_js.view/solution.js rename to 1-js/5-data-types/08-map-set-weakmap-weakset/1-filter-anagrams/_js.view/solution.js diff --git a/1-js/5-data-types/07-map-set-weakmap-weakset/1-filter-anagrams/_js.view/test.js b/1-js/5-data-types/08-map-set-weakmap-weakset/1-filter-anagrams/_js.view/test.js similarity index 100% rename from 1-js/5-data-types/07-map-set-weakmap-weakset/1-filter-anagrams/_js.view/test.js rename to 1-js/5-data-types/08-map-set-weakmap-weakset/1-filter-anagrams/_js.view/test.js diff --git a/1-js/5-data-types/07-map-set-weakmap-weakset/1-filter-anagrams/solution.md b/1-js/5-data-types/08-map-set-weakmap-weakset/1-filter-anagrams/solution.md similarity index 100% rename from 1-js/5-data-types/07-map-set-weakmap-weakset/1-filter-anagrams/solution.md rename to 1-js/5-data-types/08-map-set-weakmap-weakset/1-filter-anagrams/solution.md diff --git a/1-js/5-data-types/07-map-set-weakmap-weakset/1-filter-anagrams/task.md b/1-js/5-data-types/08-map-set-weakmap-weakset/1-filter-anagrams/task.md similarity index 100% rename from 1-js/5-data-types/07-map-set-weakmap-weakset/1-filter-anagrams/task.md rename to 1-js/5-data-types/08-map-set-weakmap-weakset/1-filter-anagrams/task.md diff --git a/1-js/5-data-types/07-map-set-weakmap-weakset/2-recipients-set/solution.md b/1-js/5-data-types/08-map-set-weakmap-weakset/2-recipients-set/solution.md similarity index 100% rename from 1-js/5-data-types/07-map-set-weakmap-weakset/2-recipients-set/solution.md rename to 1-js/5-data-types/08-map-set-weakmap-weakset/2-recipients-set/solution.md diff --git a/1-js/5-data-types/07-map-set-weakmap-weakset/2-recipients-set/task.md b/1-js/5-data-types/08-map-set-weakmap-weakset/2-recipients-set/task.md similarity index 100% rename from 1-js/5-data-types/07-map-set-weakmap-weakset/2-recipients-set/task.md rename to 1-js/5-data-types/08-map-set-weakmap-weakset/2-recipients-set/task.md diff --git a/1-js/5-data-types/07-map-set-weakmap-weakset/article.md b/1-js/5-data-types/08-map-set-weakmap-weakset/article.md similarity index 100% rename from 1-js/5-data-types/07-map-set-weakmap-weakset/article.md rename to 1-js/5-data-types/08-map-set-weakmap-weakset/article.md diff --git a/1-js/5-data-types/08-json/1-serialize-object/solution.md b/1-js/5-data-types/09-json/1-serialize-object/solution.md similarity index 100% rename from 1-js/5-data-types/08-json/1-serialize-object/solution.md rename to 1-js/5-data-types/09-json/1-serialize-object/solution.md diff --git a/1-js/5-data-types/08-json/1-serialize-object/task.md b/1-js/5-data-types/09-json/1-serialize-object/task.md similarity index 100% rename from 1-js/5-data-types/08-json/1-serialize-object/task.md rename to 1-js/5-data-types/09-json/1-serialize-object/task.md diff --git a/1-js/5-data-types/08-json/2-serialize-event-circular/solution.md b/1-js/5-data-types/09-json/2-serialize-event-circular/solution.md similarity index 100% rename from 1-js/5-data-types/08-json/2-serialize-event-circular/solution.md rename to 1-js/5-data-types/09-json/2-serialize-event-circular/solution.md diff --git a/1-js/5-data-types/08-json/2-serialize-event-circular/task.md b/1-js/5-data-types/09-json/2-serialize-event-circular/task.md similarity index 100% rename from 1-js/5-data-types/08-json/2-serialize-event-circular/task.md rename to 1-js/5-data-types/09-json/2-serialize-event-circular/task.md diff --git a/1-js/5-data-types/08-json/article.md b/1-js/5-data-types/09-json/article.md similarity index 100% rename from 1-js/5-data-types/08-json/article.md rename to 1-js/5-data-types/09-json/article.md diff --git a/1-js/5-data-types/08-json/json-meetup.png b/1-js/5-data-types/09-json/json-meetup.png similarity index 100% rename from 1-js/5-data-types/08-json/json-meetup.png rename to 1-js/5-data-types/09-json/json-meetup.png diff --git a/1-js/5-data-types/08-json/json-meetup@2x.png b/1-js/5-data-types/09-json/json-meetup@2x.png similarity index 100% rename from 1-js/5-data-types/08-json/json-meetup@2x.png rename to 1-js/5-data-types/09-json/json-meetup@2x.png diff --git a/1-js/5-data-types/09-property-flags-descriptors/article.md b/1-js/5-data-types/10-property-flags-descriptors/article.md similarity index 100% rename from 1-js/5-data-types/09-property-flags-descriptors/article.md rename to 1-js/5-data-types/10-property-flags-descriptors/article.md diff --git a/1-js/5-data-types/10-property-accessors/article.md b/1-js/5-data-types/11-property-accessors/article.md similarity index 100% rename from 1-js/5-data-types/10-property-accessors/article.md rename to 1-js/5-data-types/11-property-accessors/article.md