@@ -244,7 +248,7 @@ As the function finishes, its execution context is not needed any more, so it's
-The execution of `pow(2, 2)` is resumed. It has the result of the subcall `pow(2, 1)`, so it also can finish the evaluation of `x * pow(x, n-1)`, returning `4`.
+The execution of `pow(2, 2)` is resumed. It has the result of the subcall `pow(2, 1)`, so it also can finish the evaluation of `x * pow(x, n - 1)`, returning `4`.
Then the previous context is restored:
@@ -269,7 +273,7 @@ A loop-based algorithm is more memory-saving:
function pow(x, n) {
let result = 1;
- for(let i = 0; i < n; i++) {
+ for (let i = 0; i < n; i++) {
result *= x;
}
@@ -281,7 +285,7 @@ The iterative `pow` uses a single context changing `i` and `result` in the proce
**Any recursion can be rewritten as a loop. The loop variant usually can be made more effective.**
-...But sometimes the rewrite is non-trivial, especially when function uses different recursive subcalls depending on conditions and merges their results or when the branching is more intricate. And the optimization may be unneeded and totally not worth the efforts.
+...But sometimes the rewrite is non-trivial, especially when a function uses different recursive subcalls depending on conditions and merges their results or when the branching is more intricate. And the optimization may be unneeded and totally not worth the efforts.
Recursion can give a shorter code, easier to understand and support. Optimizations are not required in every place, mostly we need a good code, that's why it's used.
@@ -289,7 +293,7 @@ Recursion can give a shorter code, easier to understand and support. Optimizatio
Another great application of the recursion is a recursive traversal.
-Imagine, we have an company. The staff structure can be presented as an object:
+Imagine, we have a company. The staff structure can be presented as an object:
```js
let company = {
@@ -298,7 +302,7 @@ let company = {
salary: 1000
}, {
name: 'Alice',
- salary: 600
+ salary: 1600
}],
development: {
@@ -321,32 +325,32 @@ let company = {
In other words, a company has departments.
- A department may have an array of staff. For instance, `sales` department has 2 employees: John and Alice.
-- Or a department may split into subdepartments, like `development` has two branches: `sites` and `internals`. Each of them has the own staff.
+- Or a department may split into subdepartments, like `development` has two branches: `sites` and `internals`. Each of them has their own staff.
- It is also possible that when a subdepartment grows, it divides into subsubdepartments (or teams).
For instance, the `sites` department in the future may be split into teams for `siteA` and `siteB`. And they, potentially, can split even more. That's not on the picture, just something to have in mind.
Now let's say we want a function to get the sum of all salaries. How can we do that?
-An iterative approach is not easy, because the structure is not simple. The first idea may be to make a `for` loop over `company` with nested subloop over 1st level departments. But then we need more nested subloops to iterate over the staff in 2nd level departments like `sites`. ...And then another subloop inside those for 3rd level departments that might appear in the future? Should we stop on level 3 or make 4 levels of loops? If we put 3-4 nested subloops in the code to traverse a single object, it becomes rather ugly.
+An iterative approach is not easy, because the structure is not simple. The first idea may be to make a `for` loop over `company` with nested subloop over 1st level departments. But then we need more nested subloops to iterate over the staff in 2nd level departments like `sites`... And then another subloop inside those for 3rd level departments that might appear in the future? If we put 3-4 nested subloops in the code to traverse a single object, it becomes rather ugly.
Let's try recursion.
As we can see, when our function gets a department to sum, there are two possible cases:
-1. Either it's a "simple" department with an *array of people* -- then we can sum the salaries in a simple loop.
-2. Or it's *an object with `N` subdepartments* -- then we can make `N` recursive calls to get the sum for each of the subdeps and combine the results.
+1. Either it's a "simple" department with an *array* of people -- then we can sum the salaries in a simple loop.
+2. Or it's *an object* with `N` subdepartments -- then we can make `N` recursive calls to get the sum for each of the subdeps and combine the results.
-The (1) is the base of recursion, the trivial case.
+The 1st case is the base of recursion, the trivial case, when we get an array.
-The (2) is the recursive step. A complex task is split into subtasks for smaller departments. They may in turn split again, but sooner or later the split will finish at (1).
+The 2nd case when we get an object is the recursive step. A complex task is split into subtasks for smaller departments. They may in turn split again, but sooner or later the split will finish at (1).
The algorithm is probably even easier to read from the code:
```js run
let company = { // the same object, compressed for brevity
- sales: [{name: 'John', salary: 1000}, {name: 'Alice', salary: 600 }],
+ sales: [{name: 'John', salary: 1000}, {name: 'Alice', salary: 1600 }],
development: {
sites: [{name: 'Peter', salary: 2000}, {name: 'Alex', salary: 1800 }],
internals: [{name: 'Jack', salary: 1300}]
@@ -360,7 +364,7 @@ function sumSalaries(department) {
return department.reduce((prev, current) => prev + current.salary, 0); // sum the array
} else { // case (2)
let sum = 0;
- for(let subdep of Object.values(department)) {
+ for (let subdep of Object.values(department)) {
sum += sumSalaries(subdep); // recursively call for subdepartments, sum the results
}
return sum;
@@ -368,14 +372,14 @@ function sumSalaries(department) {
}
*/!*
-alert(sumSalaries(company)); // 6700
+alert(sumSalaries(company)); // 7700
```
The code is short and easy to understand (hopefully?). That's the power of recursion. It also works for any level of subdepartment nesting.
Here's the diagram of calls:
-
+
We can easily see the principle: for an object `{...}` subcalls are made, while arrays `[...]` are the "leaves" of the recursion tree, they give immediate result.
@@ -395,7 +399,7 @@ A company *department* is:
- Either an array of people.
- Or an object with *departments*.
-For web-developers there are much better known examples: HTML and XML documents.
+For web-developers there are much better-known examples: HTML and XML documents.
In the HTML document, an *HTML-tag* may contain a list of:
- Text pieces.
@@ -418,7 +422,7 @@ let arr = [obj1, obj2, obj3];
...But there's a problem with arrays. The "delete element" and "insert element" operations are expensive. For instance, `arr.unshift(obj)` operation has to renumber all elements to make room for a new `obj`, and if the array is big, it takes time. Same with `arr.shift()`.
-The only structural modifications that do not require mass-renumbering are those that operate with the end of array: `arr.push/pop`. So an array can be quite slow for big queues.
+The only structural modifications that do not require mass-renumbering are those that operate with the end of array: `arr.push/pop`. So an array can be quite slow for big queues, when we have to work with the beginning.
Alternatively, if we really need fast insertion/deletion, we can choose another data structure called a [linked list](https://en.wikipedia.org/wiki/Linked_list).
@@ -446,7 +450,7 @@ let list = {
Graphical representation of the list:
-
+
An alternative code for creation:
@@ -455,9 +459,10 @@ let list = { value: 1 };
list.next = { value: 2 };
list.next.next = { value: 3 };
list.next.next.next = { value: 4 };
+list.next.next.next.next = null;
```
-Here we can even more clearer see that there are multiple objects, each one has the `value` and `next` pointing to the neighbour. The `list` variable is the first object in the chain, so following `next` pointers from it we can reach any element.
+Here we can even more clearly see that there are multiple objects, each one has the `value` and `next` pointing to the neighbour. The `list` variable is the first object in the chain, so following `next` pointers from it we can reach any element.
The list can be easily split into multiple parts and later joined back:
@@ -466,7 +471,7 @@ let secondList = list.next.next;
list.next.next = null;
```
-
+
To join:
@@ -490,7 +495,7 @@ list = { value: "new item", next: list };
*/!*
```
-
+
To remove a value from the middle, change `next` of the previous one:
@@ -498,7 +503,7 @@ To remove a value from the middle, change `next` of the previous one:
list.next = list.next.next;
```
-
+
We made `list.next` jump over `1` to value `2`. The value `1` is now excluded from the chain. If it's not stored anywhere else, it will be automatically removed from the memory.
@@ -508,14 +513,17 @@ Naturally, lists are not always better than arrays. Otherwise everyone would use
The main drawback is that we can't easily access an element by its number. In an array that's easy: `arr[n]` is a direct reference. But in the list we need to start from the first item and go `next` `N` times to get the Nth element.
-...But we don't always need such operations. For instance, when we need a queue or even a [deque](https://en.wikipedia.org/wiki/Double-ended_queue) -- the ordered structure that must allow very fast adding/removing elements from both ends.
+...But we don't always need such operations. For instance, when we need a queue or even a [deque](https://en.wikipedia.org/wiki/Double-ended_queue) -- the ordered structure that must allow very fast adding/removing elements from both ends, but access to its middle is not needed.
-Sometimes it's worth to add another variable named `tail` to track the last element of the list (and update it when adding/removing elements from the end). For large sets of elements the speed difference versus arrays is huge.
+Lists can be enhanced:
+- We can add property `prev` in addition to `next` to reference the previous element, to move back easily.
+- We can also add a variable named `tail` referencing the last element of the list (and update it when adding/removing elements from the end).
+- ...The data structure may vary according to our needs.
## Summary
Terms:
-- *Recursion* is a programming term that means a "self-calling" function. Such functions can be used to solve certain tasks in elegant ways.
+- *Recursion* is a programming term that means calling a function from itself. Recursive functions can be used to solve tasks in elegant ways.
When a function calls itself, that's called a *recursion step*. The *basis* of recursion is function arguments that make the task so simple that the function does not make further calls.
@@ -527,7 +535,7 @@ Terms:
list = { value, next -> list }
```
- Trees like HTML elements tree or the department tree from this chapter are also naturally recursive: they branch and every branch can have other branches.
+ Trees like HTML elements tree or the department tree from this chapter are also naturally recursive: they have branches and every branch can have other branches.
Recursive functions can be used to walk them as we've seen in the `sumSalary` example.
diff --git a/1-js/06-advanced-functions/01-recursion/head.html b/1-js/06-advanced-functions/01-recursion/head.html
index c2ac3e8cee..bb7fe8772f 100644
--- a/1-js/06-advanced-functions/01-recursion/head.html
+++ b/1-js/06-advanced-functions/01-recursion/head.html
@@ -7,7 +7,7 @@
.function-execution-context {
border: 1px solid black;
- font-family: "Consolas", monospace;
+ font-family: 'DejaVu Sans Mono', 'Lucida Console', 'Menlo', 'Monaco', monospace;
padding: 4px 6px;
margin: 0 4px;
}
@@ -23,4 +23,4 @@
.function-execution-context-list li:first-child {
font-weight: bold;
}
-
\ No newline at end of file
+
diff --git a/1-js/06-advanced-functions/01-recursion/linked-list-0.png b/1-js/06-advanced-functions/01-recursion/linked-list-0.png
deleted file mode 100644
index 000a80da8c..0000000000
Binary files a/1-js/06-advanced-functions/01-recursion/linked-list-0.png and /dev/null differ
diff --git a/1-js/06-advanced-functions/01-recursion/linked-list-0.svg b/1-js/06-advanced-functions/01-recursion/linked-list-0.svg
new file mode 100644
index 0000000000..5d23c7a4c6
--- /dev/null
+++ b/1-js/06-advanced-functions/01-recursion/linked-list-0.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/06-advanced-functions/01-recursion/linked-list-0@2x.png b/1-js/06-advanced-functions/01-recursion/linked-list-0@2x.png
deleted file mode 100644
index 5a2368694f..0000000000
Binary files a/1-js/06-advanced-functions/01-recursion/linked-list-0@2x.png and /dev/null differ
diff --git a/1-js/06-advanced-functions/01-recursion/linked-list-remove-1.png b/1-js/06-advanced-functions/01-recursion/linked-list-remove-1.png
deleted file mode 100644
index 477989ad8a..0000000000
Binary files a/1-js/06-advanced-functions/01-recursion/linked-list-remove-1.png and /dev/null differ
diff --git a/1-js/06-advanced-functions/01-recursion/linked-list-remove-1.svg b/1-js/06-advanced-functions/01-recursion/linked-list-remove-1.svg
new file mode 100644
index 0000000000..2f37449c47
--- /dev/null
+++ b/1-js/06-advanced-functions/01-recursion/linked-list-remove-1.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/06-advanced-functions/01-recursion/linked-list-remove-1@2x.png b/1-js/06-advanced-functions/01-recursion/linked-list-remove-1@2x.png
deleted file mode 100644
index 41de7661c4..0000000000
Binary files a/1-js/06-advanced-functions/01-recursion/linked-list-remove-1@2x.png and /dev/null differ
diff --git a/1-js/06-advanced-functions/01-recursion/linked-list-split.png b/1-js/06-advanced-functions/01-recursion/linked-list-split.png
deleted file mode 100644
index ac22034905..0000000000
Binary files a/1-js/06-advanced-functions/01-recursion/linked-list-split.png and /dev/null differ
diff --git a/1-js/06-advanced-functions/01-recursion/linked-list-split.svg b/1-js/06-advanced-functions/01-recursion/linked-list-split.svg
new file mode 100644
index 0000000000..6c30721307
--- /dev/null
+++ b/1-js/06-advanced-functions/01-recursion/linked-list-split.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/06-advanced-functions/01-recursion/linked-list-split@2x.png b/1-js/06-advanced-functions/01-recursion/linked-list-split@2x.png
deleted file mode 100644
index 201c66f150..0000000000
Binary files a/1-js/06-advanced-functions/01-recursion/linked-list-split@2x.png and /dev/null differ
diff --git a/1-js/06-advanced-functions/01-recursion/linked-list.png b/1-js/06-advanced-functions/01-recursion/linked-list.png
deleted file mode 100644
index 64b6fb2b72..0000000000
Binary files a/1-js/06-advanced-functions/01-recursion/linked-list.png and /dev/null differ
diff --git a/1-js/06-advanced-functions/01-recursion/linked-list.svg b/1-js/06-advanced-functions/01-recursion/linked-list.svg
new file mode 100644
index 0000000000..c02744f390
--- /dev/null
+++ b/1-js/06-advanced-functions/01-recursion/linked-list.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/06-advanced-functions/01-recursion/linked-list@2x.png b/1-js/06-advanced-functions/01-recursion/linked-list@2x.png
deleted file mode 100644
index c28fa82594..0000000000
Binary files a/1-js/06-advanced-functions/01-recursion/linked-list@2x.png and /dev/null differ
diff --git a/1-js/06-advanced-functions/01-recursion/recursion-pow.png b/1-js/06-advanced-functions/01-recursion/recursion-pow.png
deleted file mode 100644
index 30577f89c2..0000000000
Binary files a/1-js/06-advanced-functions/01-recursion/recursion-pow.png and /dev/null differ
diff --git a/1-js/06-advanced-functions/01-recursion/recursion-pow.svg b/1-js/06-advanced-functions/01-recursion/recursion-pow.svg
new file mode 100644
index 0000000000..2b970a04a9
--- /dev/null
+++ b/1-js/06-advanced-functions/01-recursion/recursion-pow.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/06-advanced-functions/01-recursion/recursion-pow@2x.png b/1-js/06-advanced-functions/01-recursion/recursion-pow@2x.png
deleted file mode 100644
index c19973420d..0000000000
Binary files a/1-js/06-advanced-functions/01-recursion/recursion-pow@2x.png and /dev/null differ
diff --git a/1-js/06-advanced-functions/01-recursion/recursive-salaries.png b/1-js/06-advanced-functions/01-recursion/recursive-salaries.png
deleted file mode 100644
index 2b90154090..0000000000
Binary files a/1-js/06-advanced-functions/01-recursion/recursive-salaries.png and /dev/null differ
diff --git a/1-js/06-advanced-functions/01-recursion/recursive-salaries.svg b/1-js/06-advanced-functions/01-recursion/recursive-salaries.svg
new file mode 100644
index 0000000000..bd874c5ba6
--- /dev/null
+++ b/1-js/06-advanced-functions/01-recursion/recursive-salaries.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/06-advanced-functions/01-recursion/recursive-salaries@2x.png b/1-js/06-advanced-functions/01-recursion/recursive-salaries@2x.png
deleted file mode 100644
index 261ab144ed..0000000000
Binary files a/1-js/06-advanced-functions/01-recursion/recursive-salaries@2x.png and /dev/null differ
diff --git a/1-js/06-advanced-functions/02-rest-parameters-spread-operator/article.md b/1-js/06-advanced-functions/02-rest-parameters-spread-operator/article.md
deleted file mode 100644
index eaa42ab9f3..0000000000
--- a/1-js/06-advanced-functions/02-rest-parameters-spread-operator/article.md
+++ /dev/null
@@ -1,247 +0,0 @@
-# Rest parameters and spread operator
-
-Many JavaScript built-in functions support on arbitrary number of arguments.
-
-For instance:
-
-- `Math.max(arg1, arg2, ..., argN)` -- returns the greatest of the arguments.
-- `Object.assign(dest, src1, ..., srcN)` -- copies properties from `src1..N` into `dest`.
-- ...and so on.
-
-In this chapter we'll see how to do the same. And, more important, how to feel comfortable working with such functions and arrays.
-
-[cut]
-
-## Rest parameters `...`
-
-A function can be called with any number of arguments, no matter how it is defined.
-
-Like here:
-```js run
-function sum(a, b) {
- return a + b;
-}
-
-alert( sum(1, 2, 3, 4, 5) );
-```
-
-There will be no error because of "excessive" arguments. But of course in the result only the first two will be counted.
-
-The rest parameters can be mentioned in a function definition with three dots `...`. They literally mean: "gather the remaining parameters into an array".
-
-For instance, to gather all arguments into array `args`:
-
-```js run
-function sumAll(...args) { // args is the name for the array
- let sum = 0;
-
- for(let arg of args) sum += arg;
-
- return sum;
-}
-
-alert( sumAll(1) ); // 1
-alert( sumAll(1, 2) ); // 3
-alert( sumAll(1, 2, 3) ); // 6
-```
-
-We can choose to get first parameters as variables, and gather only the rest.
-
-Here the first two arguments go into variables and the rest goes to `titles` array:
-
-```js run
-function showName(firstName, lastName, ...titles) {
- alert( firstName + ' ' + lastName ); // Julius Caesar
-
- // the rest go into titles array
- // i.e. titles = ["Consul", "Imperator"]
- alert( titles[0] ); // Consul
- alert( titles[1] ); // Imperator
- alert( titles.length ); // 2
-}
-
-showName("Julius", "Caesar", "Consul", "Imperator");
-```
-
-````warn header="The rest parameters must be at the end"
-The rest parameters gather all remaining arguments, so the following has no sense:
-
-```js
-function f(arg1, ...rest, arg2) { // arg2 after ...rest ?!
- // error
-}
-```
-
-The `...rest` must always be the last.
-````
-
-## The "arguments" variable
-
-There is also a special array-like object named `arguments` that contains all arguments by their index.
-
-For instance:
-
-```js run
-function showName() {
- alert( arguments.length );
- alert( arguments[0] );
- alert( arguments[1] );
-
- // it's iterable
- // for(let arg of arguments) alert(arg);
-}
-
-// shows: 2, Julius, Caesar
-showName("Julius", "Caesar");
-
-// shows: 1, Ilya, undefined (no second argument)
-showName("Ilya");
-```
-
-In old times, rest parameters did not exist in the language, and `arguments` was the only way to get all arguments of the function no matter of their total number.
-
-And it still works, we can use it.
-
-But the downside is that although `arguments` is both array-like and iterable, it's not an array. It does not support array methods, so we can't say call `arguments.map(...)`.
-
-Also, it always has all arguments in it, we can't capture them partially, like we did with rest parameters.
-
-So when we need these features, then rest parameters are preferred.
-
-````smart header="Arrow functions do not have `\"arguments\"`"
-If we access the `arguments` object from an arrow function, it takes them from the outer "normal" function.
-
-Here's an example:
-
-```js run
-function f() {
- let showArg = () => alert(arguments[0]);
- showArg();
-}
-
-f(1); // 1
-```
-As we remember, arrow functions don't have their own `this`. Now we know they don't have the special `arguments` object either.
-
-````
-
-## Spread operator [#spread-operator]
-
-We've just seen how to get an array from the list of parameters.
-
-But sometimes we need to do exactly the reverse.
-
-For instance, there's a built-in function [Math.max](mdn:js/Math/max) that returns the greatest number from the list:
-
-```js run
-alert( Math.max(3, 5, 1) ); // 5
-```
-
-Now let's say we have an array `[3, 5, 1]`. How to call `Math.max` with it?
-
-Passing it "as it" won't work, because `Math.max` expects a list of numeric arguments, not a single array:
-
-```js run
-let arr = [3, 5, 1];
-
-*!*
-alert( Math.max(arr) ); // NaN
-*/!*
-```
-
-...And surely we can't manually list items in the code `Math.max(arg[0], arg[1], arg[2])`, because we may be unsure how much are there. As our script executes, there might be many, or there might be none. Also that would be ugly.
-
-*Spread operator* to the rescue. It looks similar to rest parameters, also using `...`, but does quite the opposite.
-
-When `...arr` is used in the function call, it "expands" an iterable object `arr` into the list of arguments.
-
-For `Math.max`:
-
-```js run
-let arr = [3, 5, 1];
-
-alert( Math.max(...arr) ); // 5 (spread turns array into a list of arguments)
-```
-
-We also can pass multiple iterables this way:
-
-```js run
-let arr1 = [1, -2, 3, 4];
-let arr2 = [8, 3, -8, 1];
-
-alert( Math.max(...arr1, ...arr2) ); // 8
-```
-
-...And even combine the spread operator with normal values:
-
-
-```js run
-let arr1 = [1, -2, 3, 4];
-let arr2 = [8, 3, -8, 1];
-
-alert( Math.max(1, ...arr1, 2, ...arr2, 25) ); // 25
-```
-
-Also spread operator can be used to merge arrays:
-
-```js run
-let arr = [3, 5, 1];
-let arr2 = [8, 9, 15];
-
-*!*
-let merged = [0, ...arr, 2, ...arr2];
-*/!*
-
-alert(merged); // 0,3,5,1,2,8,9,15 (0, then arr, then 2, then arr2)
-```
-
-In the examples above we used an array to demonstrate the spread operator, but any iterable will do.
-
-For instance, here we use spread operator to turn the string into array of characters:
-
-```js run
-let str = "Hello";
-
-alert( [...str] ); // H,e,l,l,o
-```
-
-The spread operator internally uses iterators to gather elements, the same way as `for..of` does.
-
-So, for a string, `for..of` returns characters and `...str` becomes `"h","e","l","l","o"`. The list of characters is passed to array initializer `[...str]`.
-
-For this particular task we could also use `Array.from`, because it converts an iterable (like a string) into an array:
-
-```js run
-let str = "Hello";
-
-// Array.from converts an iterable into an array
-alert( Array.from(str) ); // H,e,l,l,o
-```
-
-The result is the same as `[...str]`.
-
-But there's a subtle difference between `Array.from(obj)` and `[...obj]`:
-
-- `Array.from` operates on both array-likes and iterables.
-- The spread operator operates only on iterables.
-
-So, for the task of turning something into an array, `Array.from` appears more universal.
-
-
-## Summary
-
-When we see `"..."` in the code, it is either rest parameters or the spread operator.
-
-There's an easy way to distinguish between them:
-
-- When `...` is at the end of function parameters, it's "rest parameters" and gathers the rest of the list into the array.
-- When `...` occurs in a function call or alike, it's called a "spread operator" and expands an array into the list.
-
-Use patterns:
-
-- Rest parameters are used to create functions that accept any number of arguments.
-- The spread operator is used to pass an array to functions that normally require a list of many arguments.
-
-Together they help to travel between a list and an array of parameters with ease.
-
-All arguments of a function call are also available in "old-style" `arguments`: array-like iterable object.
diff --git a/1-js/06-advanced-functions/02-rest-parameters-spread/article.md b/1-js/06-advanced-functions/02-rest-parameters-spread/article.md
new file mode 100644
index 0000000000..dbdfbd6c0d
--- /dev/null
+++ b/1-js/06-advanced-functions/02-rest-parameters-spread/article.md
@@ -0,0 +1,295 @@
+# Rest parameters and spread syntax
+
+Many JavaScript built-in functions support an arbitrary number of arguments.
+
+For instance:
+
+- `Math.max(arg1, arg2, ..., argN)` -- returns the greatest of the arguments.
+- `Object.assign(dest, src1, ..., srcN)` -- copies properties from `src1..N` into `dest`.
+- ...and so on.
+
+In this chapter we'll learn how to do the same. And also, how to pass arrays to such functions as parameters.
+
+## Rest parameters `...`
+
+A function can be called with any number of arguments, no matter how it is defined.
+
+Like here:
+```js run
+function sum(a, b) {
+ return a + b;
+}
+
+alert( sum(1, 2, 3, 4, 5) );
+```
+
+There will be no error because of "excessive" arguments. But of course in the result only the first two will be counted, so the result in the code above is `3`.
+
+The rest of the parameters can be included in the function definition by using three dots `...` followed by the name of the array that will contain them. The dots literally mean "gather the remaining parameters into an array".
+
+For instance, to gather all arguments into array `args`:
+
+```js run
+function sumAll(...args) { // args is the name for the array
+ let sum = 0;
+
+ for (let arg of args) sum += arg;
+
+ return sum;
+}
+
+alert( sumAll(1) ); // 1
+alert( sumAll(1, 2) ); // 3
+alert( sumAll(1, 2, 3) ); // 6
+```
+
+We can choose to get the first parameters as variables, and gather only the rest.
+
+Here the first two arguments go into variables and the rest go into `titles` array:
+
+```js run
+function showName(firstName, lastName, ...titles) {
+ alert( firstName + ' ' + lastName ); // Julius Caesar
+
+ // the rest go into titles array
+ // i.e. titles = ["Consul", "Imperator"]
+ alert( titles[0] ); // Consul
+ alert( titles[1] ); // Imperator
+ alert( titles.length ); // 2
+}
+
+showName("Julius", "Caesar", "Consul", "Imperator");
+```
+
+````warn header="The rest parameters must be at the end"
+The rest parameters gather all remaining arguments, so the following does not make sense and causes an error:
+
+```js
+function f(arg1, ...rest, arg2) { // arg2 after ...rest ?!
+ // error
+}
+```
+
+The `...rest` must always be last.
+````
+
+## The "arguments" variable
+
+There is also a special array-like object named `arguments` that contains all arguments by their index.
+
+For instance:
+
+```js run
+function showName() {
+ alert( arguments.length );
+ alert( arguments[0] );
+ alert( arguments[1] );
+
+ // it's iterable
+ // for(let arg of arguments) alert(arg);
+}
+
+// shows: 2, Julius, Caesar
+showName("Julius", "Caesar");
+
+// shows: 1, Ilya, undefined (no second argument)
+showName("Ilya");
+```
+
+In old times, rest parameters did not exist in the language, and using `arguments` was the only way to get all arguments of the function. And it still works, we can find it in the old code.
+
+But the downside is that although `arguments` is both array-like and iterable, it's not an array. It does not support array methods, so we can't call `arguments.map(...)` for example.
+
+Also, it always contains all arguments. We can't capture them partially, like we did with rest parameters.
+
+So when we need these features, then rest parameters are preferred.
+
+````smart header="Arrow functions do not have `\"arguments\"`"
+If we access the `arguments` object from an arrow function, it takes them from the outer "normal" function.
+
+Here's an example:
+
+```js run
+function f() {
+ let showArg = () => alert(arguments[0]);
+ showArg();
+}
+
+f(1); // 1
+```
+
+As we remember, arrow functions don't have their own `this`. Now we know they don't have the special `arguments` object either.
+````
+
+
+## Spread syntax [#spread-syntax]
+
+We've just seen how to get an array from the list of parameters.
+
+But sometimes we need to do exactly the reverse.
+
+For instance, there's a built-in function [Math.max](mdn:js/Math/max) that returns the greatest number from a list:
+
+```js run
+alert( Math.max(3, 5, 1) ); // 5
+```
+
+Now let's say we have an array `[3, 5, 1]`. How do we call `Math.max` with it?
+
+Passing it "as is" won't work, because `Math.max` expects a list of numeric arguments, not a single array:
+
+```js run
+let arr = [3, 5, 1];
+
+*!*
+alert( Math.max(arr) ); // NaN
+*/!*
+```
+
+And surely we can't manually list items in the code `Math.max(arr[0], arr[1], arr[2])`, because we may be unsure how many there are. As our script executes, there could be a lot, or there could be none. And that would get ugly.
+
+*Spread syntax* to the rescue! It looks similar to rest parameters, also using `...`, but does quite the opposite.
+
+When `...arr` is used in the function call, it "expands" an iterable object `arr` into the list of arguments.
+
+For `Math.max`:
+
+```js run
+let arr = [3, 5, 1];
+
+alert( Math.max(...arr) ); // 5 (spread turns array into a list of arguments)
+```
+
+We also can pass multiple iterables this way:
+
+```js run
+let arr1 = [1, -2, 3, 4];
+let arr2 = [8, 3, -8, 1];
+
+alert( Math.max(...arr1, ...arr2) ); // 8
+```
+
+We can even combine the spread syntax with normal values:
+
+
+```js run
+let arr1 = [1, -2, 3, 4];
+let arr2 = [8, 3, -8, 1];
+
+alert( Math.max(1, ...arr1, 2, ...arr2, 25) ); // 25
+```
+
+Also, the spread syntax can be used to merge arrays:
+
+```js run
+let arr = [3, 5, 1];
+let arr2 = [8, 9, 15];
+
+*!*
+let merged = [0, ...arr, 2, ...arr2];
+*/!*
+
+alert(merged); // 0,3,5,1,2,8,9,15 (0, then arr, then 2, then arr2)
+```
+
+In the examples above we used an array to demonstrate the spread syntax, but any iterable will do.
+
+For instance, here we use the spread syntax to turn the string into array of characters:
+
+```js run
+let str = "Hello";
+
+alert( [...str] ); // H,e,l,l,o
+```
+
+The spread syntax internally uses iterators to gather elements, the same way as `for..of` does.
+
+So, for a string, `for..of` returns characters and `...str` becomes `"H","e","l","l","o"`. The list of characters is passed to array initializer `[...str]`.
+
+For this particular task we could also use `Array.from`, because it converts an iterable (like a string) into an array:
+
+```js run
+let str = "Hello";
+
+// Array.from converts an iterable into an array
+alert( Array.from(str) ); // H,e,l,l,o
+```
+
+The result is the same as `[...str]`.
+
+But there's a subtle difference between `Array.from(obj)` and `[...obj]`:
+
+- `Array.from` operates on both array-likes and iterables.
+- The spread syntax works only with iterables.
+
+So, for the task of turning something into an array, `Array.from` tends to be more universal.
+
+
+## Copy an array/object
+
+Remember when we talked about `Object.assign()` [in the past](info:object-copy#cloning-and-merging-object-assign)?
+
+It is possible to do the same thing with the spread syntax.
+
+```js run
+let arr = [1, 2, 3];
+
+*!*
+let arrCopy = [...arr]; // spread the array into a list of parameters
+ // then put the result into a new array
+*/!*
+
+// do the arrays have the same contents?
+alert(JSON.stringify(arr) === JSON.stringify(arrCopy)); // true
+
+// are the arrays equal?
+alert(arr === arrCopy); // false (not same reference)
+
+// modifying our initial array does not modify the copy:
+arr.push(4);
+alert(arr); // 1, 2, 3, 4
+alert(arrCopy); // 1, 2, 3
+```
+
+Note that it is possible to do the same thing to make a copy of an object:
+
+```js run
+let obj = { a: 1, b: 2, c: 3 };
+
+*!*
+let objCopy = { ...obj }; // spread the object into a list of parameters
+ // then return the result in a new object
+*/!*
+
+// do the objects have the same contents?
+alert(JSON.stringify(obj) === JSON.stringify(objCopy)); // true
+
+// are the objects equal?
+alert(obj === objCopy); // false (not same reference)
+
+// modifying our initial object does not modify the copy:
+obj.d = 4;
+alert(JSON.stringify(obj)); // {"a":1,"b":2,"c":3,"d":4}
+alert(JSON.stringify(objCopy)); // {"a":1,"b":2,"c":3}
+```
+
+This way of copying an object is much shorter than `let objCopy = Object.assign({}, obj)` or for an array `let arrCopy = Object.assign([], arr)` so we prefer to use it whenever we can.
+
+
+## Summary
+
+When we see `"..."` in the code, it is either rest parameters or the spread syntax.
+
+There's an easy way to distinguish between them:
+
+- When `...` is at the end of function parameters, it's "rest parameters" and gathers the rest of the list of arguments into an array.
+- When `...` occurs in a function call or alike, it's called a "spread syntax" and expands an array into a list.
+
+Use patterns:
+
+- Rest parameters are used to create functions that accept any number of arguments.
+- The spread syntax is used to pass an array to functions that normally require a list of many arguments.
+
+Together they help to travel between a list and an array of parameters with ease.
+
+All arguments of a function call are also available in "old-style" `arguments`: array-like iterable object.
diff --git a/1-js/06-advanced-functions/03-closure/1-closure-latest-changes/solution.md b/1-js/06-advanced-functions/03-closure/1-closure-latest-changes/solution.md
new file mode 100644
index 0000000000..7cbd85ab75
--- /dev/null
+++ b/1-js/06-advanced-functions/03-closure/1-closure-latest-changes/solution.md
@@ -0,0 +1,5 @@
+The answer is: **Pete**.
+
+A function gets outer variables as they are now, it uses the most recent values.
+
+Old variable values are not saved anywhere. When a function wants a variable, it takes the current value from its own Lexical Environment or the outer one.
diff --git a/1-js/06-advanced-functions/03-closure/1-closure-latest-changes/task.md b/1-js/06-advanced-functions/03-closure/1-closure-latest-changes/task.md
new file mode 100644
index 0000000000..819189773c
--- /dev/null
+++ b/1-js/06-advanced-functions/03-closure/1-closure-latest-changes/task.md
@@ -0,0 +1,23 @@
+importance: 5
+
+---
+
+# Does a function pickup latest changes?
+
+The function sayHi uses an external variable name. When the function runs, which value is it going to use?
+
+```js
+let name = "John";
+
+function sayHi() {
+ alert("Hi, " + name);
+}
+
+name = "Pete";
+
+sayHi(); // what will it show: "John" or "Pete"?
+```
+
+Such situations are common both in browser and server-side development. A function may be scheduled to execute later than it is created, for instance after a user action or a network request.
+
+So, the question is: does it pick up the latest changes?
diff --git a/1-js/06-advanced-functions/03-closure/1-counter-independent/solution.md b/1-js/06-advanced-functions/03-closure/1-counter-independent/solution.md
deleted file mode 100644
index cff69a25e2..0000000000
--- a/1-js/06-advanced-functions/03-closure/1-counter-independent/solution.md
+++ /dev/null
@@ -1,5 +0,0 @@
-The answer: **0,1.**
-
-Functions `counter` and `counter2` are created by different invocations of `makeCounter`.
-
-So they have independent outer Lexical Environments, each one has it's own `count`.
diff --git a/1-js/06-advanced-functions/03-closure/8-make-army/_js.view/solution.js b/1-js/06-advanced-functions/03-closure/10-make-army/_js.view/solution.js
similarity index 100%
rename from 1-js/06-advanced-functions/03-closure/8-make-army/_js.view/solution.js
rename to 1-js/06-advanced-functions/03-closure/10-make-army/_js.view/solution.js
diff --git a/1-js/06-advanced-functions/03-closure/8-make-army/_js.view/source.js b/1-js/06-advanced-functions/03-closure/10-make-army/_js.view/source.js
similarity index 100%
rename from 1-js/06-advanced-functions/03-closure/8-make-army/_js.view/source.js
rename to 1-js/06-advanced-functions/03-closure/10-make-army/_js.view/source.js
diff --git a/1-js/06-advanced-functions/03-closure/8-make-army/_js.view/test.js b/1-js/06-advanced-functions/03-closure/10-make-army/_js.view/test.js
similarity index 100%
rename from 1-js/06-advanced-functions/03-closure/8-make-army/_js.view/test.js
rename to 1-js/06-advanced-functions/03-closure/10-make-army/_js.view/test.js
diff --git a/1-js/06-advanced-functions/03-closure/10-make-army/lexenv-makearmy-empty.svg b/1-js/06-advanced-functions/03-closure/10-make-army/lexenv-makearmy-empty.svg
new file mode 100644
index 0000000000..f8c7bd6ac4
--- /dev/null
+++ b/1-js/06-advanced-functions/03-closure/10-make-army/lexenv-makearmy-empty.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/06-advanced-functions/03-closure/10-make-army/lexenv-makearmy-for-fixed.svg b/1-js/06-advanced-functions/03-closure/10-make-army/lexenv-makearmy-for-fixed.svg
new file mode 100644
index 0000000000..7611d0ef80
--- /dev/null
+++ b/1-js/06-advanced-functions/03-closure/10-make-army/lexenv-makearmy-for-fixed.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/06-advanced-functions/03-closure/10-make-army/lexenv-makearmy-while-fixed.svg b/1-js/06-advanced-functions/03-closure/10-make-army/lexenv-makearmy-while-fixed.svg
new file mode 100644
index 0000000000..d83ecbe76f
--- /dev/null
+++ b/1-js/06-advanced-functions/03-closure/10-make-army/lexenv-makearmy-while-fixed.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/06-advanced-functions/03-closure/10-make-army/solution.md b/1-js/06-advanced-functions/03-closure/10-make-army/solution.md
new file mode 100644
index 0000000000..9d99aa7178
--- /dev/null
+++ b/1-js/06-advanced-functions/03-closure/10-make-army/solution.md
@@ -0,0 +1,129 @@
+
+Let's examine what exactly happens inside `makeArmy`, and the solution will become obvious.
+
+1. It creates an empty array `shooters`:
+
+ ```js
+ let shooters = [];
+ ```
+2. Fills it with functions via `shooters.push(function)` in the loop.
+
+ Every element is a function, so the resulting array looks like this:
+
+ ```js no-beautify
+ shooters = [
+ function () { alert(i); },
+ function () { alert(i); },
+ function () { alert(i); },
+ function () { alert(i); },
+ function () { alert(i); },
+ function () { alert(i); },
+ function () { alert(i); },
+ function () { alert(i); },
+ function () { alert(i); },
+ function () { alert(i); }
+ ];
+ ```
+
+3. The array is returned from the function.
+
+ Then, later, the call to any member, e.g. `army[5]()` will get the element `army[5]` from the array (which is a function) and calls it.
+
+ Now why do all such functions show the same value, `10`?
+
+ That's because there's no local variable `i` inside `shooter` functions. When such a function is called, it takes `i` from its outer lexical environment.
+
+ Then, what will be the value of `i`?
+
+ If we look at the source:
+
+ ```js
+ function makeArmy() {
+ ...
+ let i = 0;
+ while (i < 10) {
+ let shooter = function() { // shooter function
+ alert( i ); // should show its number
+ };
+ shooters.push(shooter); // add function to the array
+ i++;
+ }
+ ...
+ }
+ ```
+
+ We can see that all `shooter` functions are created in the lexical environment of `makeArmy()` function. But when `army[5]()` is called, `makeArmy` has already finished its job, and the final value of `i` is `10` (`while` stops at `i=10`).
+
+ As the result, all `shooter` functions get the same value from the outer lexical environment and that is, the last value, `i=10`.
+
+ 
+
+ As you can see above, on each iteration of a `while {...}` block, a new lexical environment is created. So, to fix this, we can copy the value of `i` into a variable within the `while {...}` block, like this:
+
+ ```js run
+ function makeArmy() {
+ let shooters = [];
+
+ let i = 0;
+ while (i < 10) {
+ *!*
+ let j = i;
+ */!*
+ let shooter = function() { // shooter function
+ alert( *!*j*/!* ); // should show its number
+ };
+ shooters.push(shooter);
+ i++;
+ }
+
+ return shooters;
+ }
+
+ let army = makeArmy();
+
+ // Now the code works correctly
+ army[0](); // 0
+ army[5](); // 5
+ ```
+
+ Here `let j = i` declares an "iteration-local" variable `j` and copies `i` into it. Primitives are copied "by value", so we actually get an independent copy of `i`, belonging to the current loop iteration.
+
+ The shooters work correctly, because the value of `i` now lives a little bit closer. Not in `makeArmy()` Lexical Environment, but in the Lexical Environment that corresponds to the current loop iteration:
+
+ 
+
+ Such a problem could also be avoided if we used `for` in the beginning, like this:
+
+ ```js run demo
+ function makeArmy() {
+
+ let shooters = [];
+
+ *!*
+ for(let i = 0; i < 10; i++) {
+ */!*
+ let shooter = function() { // shooter function
+ alert( i ); // should show its number
+ };
+ shooters.push(shooter);
+ }
+
+ return shooters;
+ }
+
+ let army = makeArmy();
+
+ army[0](); // 0
+ army[5](); // 5
+ ```
+
+ That's essentially the same, because `for` on each iteration generates a new lexical environment, with its own variable `i`. So `shooter` generated in every iteration references its own `i`, from that very iteration.
+
+ 
+
+Now, as you've put so much effort into reading this, and the final recipe is so simple - just use `for`, you may wonder -- was it worth that?
+
+Well, if you could easily answer the question, you wouldn't read the solution. So, hopefully this task must have helped you to understand things a bit better.
+
+Besides, there are indeed cases when one prefers `while` to `for`, and other scenarios, where such problems are real.
+
diff --git a/1-js/06-advanced-functions/03-closure/10-make-army/task.md b/1-js/06-advanced-functions/03-closure/10-make-army/task.md
new file mode 100644
index 0000000000..f50c7dc209
--- /dev/null
+++ b/1-js/06-advanced-functions/03-closure/10-make-army/task.md
@@ -0,0 +1,41 @@
+importance: 5
+
+---
+
+# Army of functions
+
+The following code creates an array of `shooters`.
+
+Every function is meant to output its number. But something is wrong...
+
+```js run
+function makeArmy() {
+ let shooters = [];
+
+ let i = 0;
+ while (i < 10) {
+ let shooter = function() { // create a shooter function,
+ alert( i ); // that should show its number
+ };
+ shooters.push(shooter); // and add it to the array
+ i++;
+ }
+
+ // ...and return the array of shooters
+ return shooters;
+}
+
+let army = makeArmy();
+
+*!*
+// all shooters show 10 instead of their numbers 0, 1, 2, 3...
+army[0](); // 10 from the shooter number 0
+army[1](); // 10 from the shooter number 1
+army[2](); // 10 ...and so on.
+*/!*
+```
+
+Why do all of the shooters show the same value?
+
+Fix the code so that they work as intended.
+
diff --git a/1-js/06-advanced-functions/03-closure/2-closure-variable-access/lexenv-nested-work.svg b/1-js/06-advanced-functions/03-closure/2-closure-variable-access/lexenv-nested-work.svg
new file mode 100644
index 0000000000..8dfd8bd638
--- /dev/null
+++ b/1-js/06-advanced-functions/03-closure/2-closure-variable-access/lexenv-nested-work.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/06-advanced-functions/03-closure/2-closure-variable-access/solution.md b/1-js/06-advanced-functions/03-closure/2-closure-variable-access/solution.md
new file mode 100644
index 0000000000..0a522132fe
--- /dev/null
+++ b/1-js/06-advanced-functions/03-closure/2-closure-variable-access/solution.md
@@ -0,0 +1,9 @@
+The answer is: **Pete**.
+
+The `work()` function in the code below gets `name` from the place of its origin through the outer lexical environment reference:
+
+
+
+So, the result is `"Pete"` here.
+
+But if there were no `let name` in `makeWorker()`, then the search would go outside and take the global variable as we can see from the chain above. In that case the result would be `"John"`.
diff --git a/1-js/06-advanced-functions/03-closure/2-closure-variable-access/task.md b/1-js/06-advanced-functions/03-closure/2-closure-variable-access/task.md
new file mode 100644
index 0000000000..d12a385c81
--- /dev/null
+++ b/1-js/06-advanced-functions/03-closure/2-closure-variable-access/task.md
@@ -0,0 +1,29 @@
+importance: 5
+
+---
+
+# Which variables are available?
+
+The function `makeWorker` below makes another function and returns it. That new function can be called from somewhere else.
+
+Will it have access to the outer variables from its creation place, or the invocation place, or both?
+
+```js
+function makeWorker() {
+ let name = "Pete";
+
+ return function() {
+ alert(name);
+ };
+}
+
+let name = "John";
+
+// create a function
+let work = makeWorker();
+
+// call it
+work(); // what will it show?
+```
+
+Which value it will show? "Pete" or "John"?
diff --git a/1-js/06-advanced-functions/03-closure/3-counter-independent/solution.md b/1-js/06-advanced-functions/03-closure/3-counter-independent/solution.md
new file mode 100644
index 0000000000..25ecbea4cc
--- /dev/null
+++ b/1-js/06-advanced-functions/03-closure/3-counter-independent/solution.md
@@ -0,0 +1,5 @@
+The answer: **0,1.**
+
+Functions `counter` and `counter2` are created by different invocations of `makeCounter`.
+
+So they have independent outer Lexical Environments, each one has its own `count`.
diff --git a/1-js/06-advanced-functions/03-closure/1-counter-independent/task.md b/1-js/06-advanced-functions/03-closure/3-counter-independent/task.md
similarity index 100%
rename from 1-js/06-advanced-functions/03-closure/1-counter-independent/task.md
rename to 1-js/06-advanced-functions/03-closure/3-counter-independent/task.md
diff --git a/1-js/06-advanced-functions/03-closure/3-function-in-if/task.md b/1-js/06-advanced-functions/03-closure/3-function-in-if/task.md
deleted file mode 100644
index d0dbbeb111..0000000000
--- a/1-js/06-advanced-functions/03-closure/3-function-in-if/task.md
+++ /dev/null
@@ -1,20 +0,0 @@
-
-# Function in if
-
-Look at the code. What will be result of the call at the last line?
-
-```js run
-let phrase = "Hello";
-
-if (true) {
- let user = "John";
-
- function sayHi() {
- alert(`${phrase}, ${user}`);
- }
-}
-
-*!*
-sayHi();
-*/!*
-```
diff --git a/1-js/06-advanced-functions/03-closure/4-closure-sum/solution.md b/1-js/06-advanced-functions/03-closure/4-closure-sum/solution.md
deleted file mode 100644
index e8c8c465c2..0000000000
--- a/1-js/06-advanced-functions/03-closure/4-closure-sum/solution.md
+++ /dev/null
@@ -1,17 +0,0 @@
-For the second brackets to work, the first ones must return a function.
-
-Like this:
-
-```js run
-function sum(a) {
-
- return function(b) {
- return a + b; // takes "a" from the outer lexical environment
- };
-
-}
-
-alert( sum(1)(2) ); // 3
-alert( sum(5)(-1) ); // 4
-```
-
diff --git a/1-js/06-advanced-functions/03-closure/4-closure-sum/task.md b/1-js/06-advanced-functions/03-closure/4-closure-sum/task.md
deleted file mode 100644
index c2f3eabeb3..0000000000
--- a/1-js/06-advanced-functions/03-closure/4-closure-sum/task.md
+++ /dev/null
@@ -1,17 +0,0 @@
-importance: 4
-
----
-
-# Sum with closures
-
-Write function `sum` that works like this: `sum(a)(b) = a+b`.
-
-Yes, exactly this way, via double brackets (not a mistype).
-
-For instance:
-
-```js
-sum(1)(2) = 3
-sum(5)(-1) = 4
-```
-
diff --git a/1-js/06-advanced-functions/03-closure/2-counter-object-independent/solution.md b/1-js/06-advanced-functions/03-closure/4-counter-object-independent/solution.md
similarity index 100%
rename from 1-js/06-advanced-functions/03-closure/2-counter-object-independent/solution.md
rename to 1-js/06-advanced-functions/03-closure/4-counter-object-independent/solution.md
diff --git a/1-js/06-advanced-functions/03-closure/2-counter-object-independent/task.md b/1-js/06-advanced-functions/03-closure/4-counter-object-independent/task.md
similarity index 100%
rename from 1-js/06-advanced-functions/03-closure/2-counter-object-independent/task.md
rename to 1-js/06-advanced-functions/03-closure/4-counter-object-independent/task.md
diff --git a/1-js/06-advanced-functions/03-closure/3-function-in-if/solution.md b/1-js/06-advanced-functions/03-closure/5-function-in-if/solution.md
similarity index 100%
rename from 1-js/06-advanced-functions/03-closure/3-function-in-if/solution.md
rename to 1-js/06-advanced-functions/03-closure/5-function-in-if/solution.md
diff --git a/1-js/06-advanced-functions/03-closure/5-function-in-if/task.md b/1-js/06-advanced-functions/03-closure/5-function-in-if/task.md
new file mode 100644
index 0000000000..4e386eec5e
--- /dev/null
+++ b/1-js/06-advanced-functions/03-closure/5-function-in-if/task.md
@@ -0,0 +1,22 @@
+importance: 5
+
+---
+# Function in if
+
+Look at the code. What will be the result of the call at the last line?
+
+```js run
+let phrase = "Hello";
+
+if (true) {
+ let user = "John";
+
+ function sayHi() {
+ alert(`${phrase}, ${user}`);
+ }
+}
+
+*!*
+sayHi();
+*/!*
+```
diff --git a/1-js/06-advanced-functions/03-closure/6-closure-sum/solution.md b/1-js/06-advanced-functions/03-closure/6-closure-sum/solution.md
new file mode 100644
index 0000000000..a6679cd209
--- /dev/null
+++ b/1-js/06-advanced-functions/03-closure/6-closure-sum/solution.md
@@ -0,0 +1,17 @@
+For the second parentheses to work, the first ones must return a function.
+
+Like this:
+
+```js run
+function sum(a) {
+
+ return function(b) {
+ return a + b; // takes "a" from the outer lexical environment
+ };
+
+}
+
+alert( sum(1)(2) ); // 3
+alert( sum(5)(-1) ); // 4
+```
+
diff --git a/1-js/06-advanced-functions/03-closure/6-closure-sum/task.md b/1-js/06-advanced-functions/03-closure/6-closure-sum/task.md
new file mode 100644
index 0000000000..b45758562e
--- /dev/null
+++ b/1-js/06-advanced-functions/03-closure/6-closure-sum/task.md
@@ -0,0 +1,17 @@
+importance: 4
+
+---
+
+# Sum with closures
+
+Write function `sum` that works like this: `sum(a)(b) = a+b`.
+
+Yes, exactly this way, using double parentheses (not a mistype).
+
+For instance:
+
+```js
+sum(1)(2) = 3
+sum(5)(-1) = 4
+```
+
diff --git a/1-js/06-advanced-functions/03-closure/6-filter-through-function/solution.md b/1-js/06-advanced-functions/03-closure/6-filter-through-function/solution.md
deleted file mode 100644
index 5bbc33b025..0000000000
--- a/1-js/06-advanced-functions/03-closure/6-filter-through-function/solution.md
+++ /dev/null
@@ -1,26 +0,0 @@
-
-# Filter inBetween
-
-```js run
-function inBetween(a, b) {
- return function(x) {
- return x >= a && x <= b;
- };
-}
-
-let arr = [1, 2, 3, 4, 5, 6, 7];
-alert( arr.filter(inBetween(3, 6)) ); // 3,4,5,6
-```
-
-# Filter inArray
-
-```js run
-function inArray(arr) {
- return function(x) {
- return arr.includes(x);
- };
-}
-
-let arr = [1, 2, 3, 4, 5, 6, 7];
-alert( arr.filter(inArray([1, 2, 10])) ); // 1,2
-```
diff --git a/1-js/06-advanced-functions/03-closure/7-let-scope/solution.md b/1-js/06-advanced-functions/03-closure/7-let-scope/solution.md
new file mode 100644
index 0000000000..b16b352902
--- /dev/null
+++ b/1-js/06-advanced-functions/03-closure/7-let-scope/solution.md
@@ -0,0 +1,40 @@
+The result is: **error**.
+
+Try running it:
+
+```js run
+let x = 1;
+
+function func() {
+*!*
+ console.log(x); // ReferenceError: Cannot access 'x' before initialization
+*/!*
+ let x = 2;
+}
+
+func();
+```
+
+In this example we can observe the peculiar difference between a "non-existing" and "uninitialized" variable.
+
+As you may have read in the article [](info:closure), a variable starts in the "uninitialized" state from the moment when the execution enters a code block (or a function). And it stays uninitalized until the corresponding `let` statement.
+
+In other words, a variable technically exists, but can't be used before `let`.
+
+The code above demonstrates it.
+
+```js
+function func() {
+*!*
+ // the local variable x is known to the engine from the beginning of the function,
+ // but "uninitialized" (unusable) until let ("dead zone")
+ // hence the error
+*/!*
+
+ console.log(x); // ReferenceError: Cannot access 'x' before initialization
+
+ let x = 2;
+}
+```
+
+This zone of temporary unusability of a variable (from the beginning of the code block till `let`) is sometimes called the "dead zone".
diff --git a/1-js/06-advanced-functions/03-closure/7-let-scope/task.md b/1-js/06-advanced-functions/03-closure/7-let-scope/task.md
new file mode 100644
index 0000000000..fb7445e66a
--- /dev/null
+++ b/1-js/06-advanced-functions/03-closure/7-let-scope/task.md
@@ -0,0 +1,21 @@
+importance: 4
+
+---
+
+# Is variable visible?
+
+What will be the result of this code?
+
+```js
+let x = 1;
+
+function func() {
+ console.log(x); // ?
+
+ let x = 2;
+}
+
+func();
+```
+
+P.S. There's a pitfall in this task. The solution is not obvious.
diff --git a/1-js/06-advanced-functions/03-closure/7-sort-by-field/solution.md b/1-js/06-advanced-functions/03-closure/7-sort-by-field/solution.md
deleted file mode 100644
index bd57085eaf..0000000000
--- a/1-js/06-advanced-functions/03-closure/7-sort-by-field/solution.md
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-```js run
-let users = [
- { name: "John", age: 20, surname: "Johnson" },
- { name: "Pete", age: 18, surname: "Peterson" },
- { name: "Ann", age: 19, surname: "Hathaway" }
-];
-
-*!*
-function byField(field) {
- return (a, b) => a[field] > b[field] ? 1 : -1;
-}
-*/!*
-
-users.sort(byField('name'));
-users.forEach(user => alert(user.name)); // Ann, John, Pete
-
-users.sort(byField('age'));
-users.forEach(user => alert(user.name)); // Pete, Ann, John
-```
-
diff --git a/1-js/06-advanced-functions/03-closure/6-filter-through-function/_js.view/solution.js b/1-js/06-advanced-functions/03-closure/8-filter-through-function/_js.view/solution.js
similarity index 100%
rename from 1-js/06-advanced-functions/03-closure/6-filter-through-function/_js.view/solution.js
rename to 1-js/06-advanced-functions/03-closure/8-filter-through-function/_js.view/solution.js
diff --git a/1-js/06-advanced-functions/03-closure/6-filter-through-function/_js.view/source.js b/1-js/06-advanced-functions/03-closure/8-filter-through-function/_js.view/source.js
similarity index 100%
rename from 1-js/06-advanced-functions/03-closure/6-filter-through-function/_js.view/source.js
rename to 1-js/06-advanced-functions/03-closure/8-filter-through-function/_js.view/source.js
diff --git a/1-js/06-advanced-functions/03-closure/6-filter-through-function/_js.view/test.js b/1-js/06-advanced-functions/03-closure/8-filter-through-function/_js.view/test.js
similarity index 100%
rename from 1-js/06-advanced-functions/03-closure/6-filter-through-function/_js.view/test.js
rename to 1-js/06-advanced-functions/03-closure/8-filter-through-function/_js.view/test.js
diff --git a/1-js/06-advanced-functions/03-closure/8-filter-through-function/solution.md b/1-js/06-advanced-functions/03-closure/8-filter-through-function/solution.md
new file mode 100644
index 0000000000..46c5514a8d
--- /dev/null
+++ b/1-js/06-advanced-functions/03-closure/8-filter-through-function/solution.md
@@ -0,0 +1,26 @@
+
+# Filter inBetween
+
+```js run
+function inBetween(a, b) {
+ return function(x) {
+ return x >= a && x <= b;
+ };
+}
+
+let arr = [1, 2, 3, 4, 5, 6, 7];
+alert( arr.filter(inBetween(3, 6)) ); // 3,4,5,6
+```
+
+# Filter inArray
+
+```js run demo
+function inArray(arr) {
+ return function(x) {
+ return arr.includes(x);
+ };
+}
+
+let arr = [1, 2, 3, 4, 5, 6, 7];
+alert( arr.filter(inArray([1, 2, 10])) ); // 1,2
+```
diff --git a/1-js/06-advanced-functions/03-closure/6-filter-through-function/task.md b/1-js/06-advanced-functions/03-closure/8-filter-through-function/task.md
similarity index 100%
rename from 1-js/06-advanced-functions/03-closure/6-filter-through-function/task.md
rename to 1-js/06-advanced-functions/03-closure/8-filter-through-function/task.md
diff --git a/1-js/06-advanced-functions/03-closure/8-make-army/lexenv-makearmy.png b/1-js/06-advanced-functions/03-closure/8-make-army/lexenv-makearmy.png
deleted file mode 100644
index d51e8167f8..0000000000
Binary files a/1-js/06-advanced-functions/03-closure/8-make-army/lexenv-makearmy.png and /dev/null differ
diff --git a/1-js/06-advanced-functions/03-closure/8-make-army/lexenv-makearmy@2x.png b/1-js/06-advanced-functions/03-closure/8-make-army/lexenv-makearmy@2x.png
deleted file mode 100644
index e70edbd6d4..0000000000
Binary files a/1-js/06-advanced-functions/03-closure/8-make-army/lexenv-makearmy@2x.png and /dev/null differ
diff --git a/1-js/06-advanced-functions/03-closure/8-make-army/solution.md b/1-js/06-advanced-functions/03-closure/8-make-army/solution.md
deleted file mode 100644
index 03c34b0754..0000000000
--- a/1-js/06-advanced-functions/03-closure/8-make-army/solution.md
+++ /dev/null
@@ -1,121 +0,0 @@
-
-Let's examine what's done inside `makeArmy`, and the solution will become obvious.
-
-1. It creates an empty array `shooters`:
-
- ```js
- let shooters = [];
- ```
-2. Fills it in the loop via `shooters.push(function...)`.
-
- Every element is a function, so the resulting array looks like this:
-
- ```js no-beautify
- shooters = [
- function () { alert(i); },
- function () { alert(i); },
- function () { alert(i); },
- function () { alert(i); },
- function () { alert(i); },
- function () { alert(i); },
- function () { alert(i); },
- function () { alert(i); },
- function () { alert(i); },
- function () { alert(i); }
- ];
- ```
-
-3. The array is returned from the function.
-
-Then, later, the call to `army[5]()` will get the element `army[5]` from the array (it will be a function) and call it.
-
-Now why all such functions show the same?
-
-That's because there's no local variable `i` inside `shooter` functions. When such a function is called, it takes `i` from its outer lexical environment.
-
-What will be the value of `i`?
-
-If we look at the source:
-
-```js
-function makeArmy() {
- ...
- let i = 0;
- while (i < 10) {
- let shooter = function() { // shooter function
- alert( i ); // should show its number
- };
- ...
- }
- ...
-}
-```
-
-...We can see that it lives in the lexical environment associated with the current `makeArmy()` run. But when `army[5]()` is called, `makeArmy` has already finished its job, and `i` has the last value: `10` (the end of `while`).
-
-As a result, all `shooter` functions get from the outer lexical envrironment the same, last value `i=10`.
-
-The fix can be very simple:
-
-```js run
-function makeArmy() {
-
- let shooters = [];
-
-*!*
- for(let i = 0; i < 10; i++) {
-*/!*
- let shooter = function() { // shooter function
- alert( i ); // should show its number
- };
- shooters.push(shooter);
- }
-
- return shooters;
-}
-
-let army = makeArmy();
-
-army[0](); // 0
-army[5](); // 5
-```
-
-Now it works correctly, because every time the code block in `for (..) {...}` is executed, a new Lexical Environment is created for it, with the corresponding value of `i`.
-
-So, the value of `i` now lives a little bit closer. Not in `makeArmy()` Lexical Environment, but in the Lexical Environment that corresponds the current loop iteration. A `shooter` gets the value exactly from the one where it was created.
-
-
-
-Here we rewrote `while` into `for`.
-
-Another trick could be possible, let's see it for better understanding of the subject:
-
-
-```js run
-function makeArmy() {
- let shooters = [];
-
- let i = 0;
- while (i < 10) {
-*!*
- let j = i;
-*/!*
- let shooter = function() { // shooter function
- alert( *!*j*/!* ); // should show its number
- };
- shooters.push(shooter);
- i++;
- }
-
- return shooters;
-}
-
-let army = makeArmy();
-
-army[0](); // 0
-army[5](); // 5
-```
-
-The `while` loop, just like `for`, makes a new Lexical Environment for each run. So here we make sure that it gets the right value for a `shooter`.
-
-We copy `let j = i`. This makes a loop body local `j` and copies the value of `i` to it. Primitives are copied "by value", so we actually get a complete independent copy of `i`, belonging to the current loop iteration.
diff --git a/1-js/06-advanced-functions/03-closure/8-make-army/task.md b/1-js/06-advanced-functions/03-closure/8-make-army/task.md
deleted file mode 100644
index ede8fd0458..0000000000
--- a/1-js/06-advanced-functions/03-closure/8-make-army/task.md
+++ /dev/null
@@ -1,35 +0,0 @@
-importance: 5
-
----
-
-# Army of functions
-
-The following code creates an array of `shooters`.
-
-Every function is meant to output its number. But something is wrong...
-
-```js run
-function makeArmy() {
- let shooters = [];
-
- let i = 0;
- while (i < 10) {
- let shooter = function() { // shooter function
- alert( i ); // should show its number
- };
- shooters.push(shooter);
- i++;
- }
-
- return shooters;
-}
-
-let army = makeArmy();
-
-army[0](); // the shooter number 0 shows 10
-army[5](); // and number 5 also outputs 10...
-// ... all shooters show 10 instead of their 0, 1, 2, 3...
-```
-
-Why all shooters show the same? Fix the code so that they work as intended.
-
diff --git a/1-js/06-advanced-functions/03-closure/9-sort-by-field/_js.view/solution.js b/1-js/06-advanced-functions/03-closure/9-sort-by-field/_js.view/solution.js
new file mode 100644
index 0000000000..8a71c869d9
--- /dev/null
+++ b/1-js/06-advanced-functions/03-closure/9-sort-by-field/_js.view/solution.js
@@ -0,0 +1,3 @@
+function byField(fieldName){
+ return (a, b) => a[fieldName] > b[fieldName] ? 1 : -1;
+}
diff --git a/1-js/06-advanced-functions/03-closure/9-sort-by-field/_js.view/source.js b/1-js/06-advanced-functions/03-closure/9-sort-by-field/_js.view/source.js
new file mode 100644
index 0000000000..23b4338340
--- /dev/null
+++ b/1-js/06-advanced-functions/03-closure/9-sort-by-field/_js.view/source.js
@@ -0,0 +1,5 @@
+function byField(fieldName){
+
+ // Your code goes here.
+
+}
diff --git a/1-js/06-advanced-functions/03-closure/9-sort-by-field/_js.view/test.js b/1-js/06-advanced-functions/03-closure/9-sort-by-field/_js.view/test.js
new file mode 100644
index 0000000000..802f28c4d8
--- /dev/null
+++ b/1-js/06-advanced-functions/03-closure/9-sort-by-field/_js.view/test.js
@@ -0,0 +1,39 @@
+describe("byField", function(){
+
+ let users = [
+ { name: "John", age: 20, surname: "Johnson" },
+ { name: "Pete", age: 18, surname: "Peterson" },
+ { name: "Ann", age: 19, surname: "Hathaway" },
+ ];
+
+ it("sorts users by name", function(){
+ let nameSortedKey = [
+ { name: "Ann", age: 19, surname: "Hathaway" },
+ { name: "John", age: 20, surname: "Johnson"},
+ { name: "Pete", age: 18, surname: "Peterson" },
+ ];
+ let nameSortedAnswer = users.sort(byField("name"));
+ assert.deepEqual(nameSortedKey, nameSortedAnswer);
+ });
+
+ it("sorts users by age", function(){
+ let ageSortedKey = [
+ { name: "Pete", age: 18, surname: "Peterson" },
+ { name: "Ann", age: 19, surname: "Hathaway" },
+ { name: "John", age: 20, surname: "Johnson"},
+ ];
+ let ageSortedAnswer = users.sort(byField("age"));
+ assert.deepEqual(ageSortedKey, ageSortedAnswer);
+ });
+
+ it("sorts users by surname", function(){
+ let surnameSortedKey = [
+ { name: "Ann", age: 19, surname: "Hathaway" },
+ { name: "John", age: 20, surname: "Johnson"},
+ { name: "Pete", age: 18, surname: "Peterson" },
+ ];
+ let surnameSortedAnswer = users.sort(byField("surname"));
+ assert.deepEqual(surnameSortedAnswer, surnameSortedKey);
+ });
+
+});
diff --git a/1-js/06-advanced-functions/03-closure/9-sort-by-field/solution.md b/1-js/06-advanced-functions/03-closure/9-sort-by-field/solution.md
new file mode 100644
index 0000000000..8b13789179
--- /dev/null
+++ b/1-js/06-advanced-functions/03-closure/9-sort-by-field/solution.md
@@ -0,0 +1 @@
+
diff --git a/1-js/06-advanced-functions/03-closure/7-sort-by-field/task.md b/1-js/06-advanced-functions/03-closure/9-sort-by-field/task.md
similarity index 100%
rename from 1-js/06-advanced-functions/03-closure/7-sort-by-field/task.md
rename to 1-js/06-advanced-functions/03-closure/9-sort-by-field/task.md
diff --git a/1-js/06-advanced-functions/03-closure/article.md b/1-js/06-advanced-functions/03-closure/article.md
index 7e3b14db25..cb43a7968f 100644
--- a/1-js/06-advanced-functions/03-closure/article.md
+++ b/1-js/06-advanced-functions/03-closure/article.md
@@ -1,204 +1,110 @@
-# Closure
+# Variable scope, closure
-JavaScript is a very function-oriented language. It gives a lot of freedom. A function can be created at one moment, then copied to another variable or passed as an argument to another function and called from a totally different place later.
+JavaScript is a very function-oriented language. It gives us a lot of freedom. A function can be created at any moment, passed as an argument to another function, and then called from a totally different place of code later.
-We know that a function can access variables outside of it. And this feature is used quite often.
+We already know that a function can access variables outside of it ("outer" variables).
-But what happens when an outer variables changes? Does a function get a most recent value or the one that existed when the function was created?
+But what happens if outer variables change since a function is created? Will the function get newer values or the old ones?
-Also, what happens when a function travels to another place of the code and is called from there -- does it get access to outer variables in the new place?
+And what if a function is passed along as an argument and called from another place of code, will it get access to outer variables at the new place?
-Different languages behave differently here, in this chapter we cover JavaScript.
+Let's expand our knowledge to understand these scenarios and more complex ones.
-[cut]
+```smart header="We'll talk about `let/const` variables here"
+In JavaScript, there are 3 ways to declare a variable: `let`, `const` (the modern ones), and `var` (the remnant of the past).
-## A couple of questions
-
-Let's formulate two questions for the seed, and then study internal mechanics piece-by-piece, so that you'll be able to answer these questions and more complex ones in the future.
-
-1. The function `sayHi` uses an external variable `name`. When the function runs, which value of these two it's going to use?
-
- ```js
- let name = "John";
-
- function sayHi() {
- alert("Hi, " + name);
- }
-
- name = "Pete";
-
- *!*
- sayHi(); // what will it show: "John" or "Pete"?
- */!*
- ```
-
- Such situations are common in both browser and server-side development. A function may be scheduled to execute later than it is created, for instance after a user action or a network request.
-
- So, the question is: does it pick up latest changes?
-
-
-2. The function `makeWorker` makes another function and returns it. That new function can be called from somewhere else. Will it have access to outer variables from its creation place or the invocation place or maybe both?
-
- ```js
- function makeWorker() {
- let name = "Pete";
-
- return function() {
- alert(name);
- };
- }
-
- let name = "John";
-
- // create a function
- let work = makeWorker();
-
- // call it
- *!*
- work(); // what will it show? "Pete" (name where created) or "John" (name where called)?
- */!*
- ```
-
-
-## Lexical Environment
-
-To understand what's going on, let's first discuss what a "variable" technically is.
-
-In JavaScript, every running function, code block and the script as a whole have an associated object named *Lexical Environment*.
-
-The Lexical Environment object consists of two parts:
-
-1. *Environment Record* -- an object that has all local variables as its properties (and some other information like the value of `this`).
-2. A reference to the *outer lexical environment*, usually the one associated with the code lexically right outside of it (outside of the current figure brackets).a
-
-So, a "variable" is just a property of the special internal object, Environment Record. "To get or change a variable" means "to get or change the property of that object".
-
-For instance, in this simple code, there is only one Lexical Environment:
-
-
-
-This is a so-called global Lexical Environment, associated with the whole script. For browsers, all `
- ```
+That said, using global variables is generally discouraged. There should be as few global variables as possible. The code design where a function gets "input" variables and produces certain "outcome" is clearer, less prone to errors and easier to test than if it uses outer or global variables.
- Here, first two alerts use the current window, and the latter two take variables from `iframe` window. Can be any variables if `iframe` originates from the same protocol/host/port.
+## Using for polyfills
-## "this" and global object
+We use the global object to test for support of modern language features.
-Sometimes, the value of `this` is exactly the global object. That's rarely used, but some scripts rely on that.
+For instance, test if a built-in `Promise` object exists (it doesn't in really old browsers):
+```js run
+if (!window.Promise) {
+ alert("Your browser is really old!");
+}
+```
-1. In the browser, the value of `this` in the global area is `window`:
+If there's none (say, we're in an old browser), we can create "polyfills": add functions that are not supported by the environment, but exist in the modern standard.
- ```js run
- // outside of functions
- alert( this === window ); // true
- ```
+```js run
+if (!window.Promise) {
+ window.Promise = ... // custom implementation of the modern language feature
+}
+```
- Other, non-browser environments, may use another value for `this` in such cases.
+## Summary
-2. When a function with `this` is called in non-strict mode, it gets the global object as `this`:
- ```js run no-strict
- // not in strict mode (!)
- function f() {
- alert(this); // [object Window]
- }
+- The global object holds variables that should be available everywhere.
- f(); // called without an object
- ```
+ That includes JavaScript built-ins, such as `Array` and environment-specific values, such as `window.innerHeight` -- the window height in the browser.
+- The global object has a universal name `globalThis`.
- By specification, `this` in this case must be the global object, even in non-browser environments like Node.JS. That's for compatibility with old scripts, in strict mode `this` would be `undefined`.
+ ...But more often is referred by "old-school" environment-specific names, such as `window` (browser) and `global` (Node.js).
+- We should store values in the global object only if they're truly global for our project. And keep their number at minimum.
+- In-browser, unless we're using [modules](info:modules), global functions and variables declared with `var` become a property of the global object.
+- To make our code future-proof and easier to understand, we should access properties of the global object directly, as `window.x`.
diff --git a/1-js/06-advanced-functions/06-function-object/2-counter-inc-dec/task.md b/1-js/06-advanced-functions/06-function-object/2-counter-inc-dec/task.md
index e34bb67bb0..a11821d679 100644
--- a/1-js/06-advanced-functions/06-function-object/2-counter-inc-dec/task.md
+++ b/1-js/06-advanced-functions/06-function-object/2-counter-inc-dec/task.md
@@ -7,8 +7,8 @@ importance: 5
Modify the code of `makeCounter()` so that the counter can also decrease and set the number:
- `counter()` should return the next number (as before).
-- `counter.set(value)` should set the `count` to `value`.
-- `counter.decrease(value)` should decrease the `count` by 1.
+- `counter.set(value)` should set the counter to `value`.
+- `counter.decrease()` should decrease the counter by 1.
See the sandbox code for the complete usage example.
diff --git a/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/_js.view/solution.js b/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/_js.view/solution.js
new file mode 100644
index 0000000000..c7d7d734ea
--- /dev/null
+++ b/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/_js.view/solution.js
@@ -0,0 +1,15 @@
+function sum(a) {
+
+ let currentSum = a;
+
+ function f(b) {
+ currentSum += b;
+ return f;
+ }
+
+ f.toString = function() {
+ return currentSum;
+ };
+
+ return f;
+}
diff --git a/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/_js.view/source.js b/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/_js.view/source.js
new file mode 100644
index 0000000000..f10dca5dc8
--- /dev/null
+++ b/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/_js.view/source.js
@@ -0,0 +1,12 @@
+function sum(a){
+ // Your code goes here.
+
+}
+
+/*
+sum(1)(2) == 3; // 1 + 2
+sum(1)(2)(3) == 6; // 1 + 2 + 3
+sum(5)(-1)(2) == 6
+sum(6)(-1)(-2)(-3) == 0
+sum(0)(1)(2)(3)(4)(5) == 15
+*/
diff --git a/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/_js.view/test.js b/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/_js.view/test.js
new file mode 100644
index 0000000000..ed567d3306
--- /dev/null
+++ b/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/_js.view/test.js
@@ -0,0 +1,19 @@
+describe("sum", function(){
+
+ it("sum(1)(2) == 3", function(){
+ assert.equal(3, sum(1)(2));
+ });
+
+ it("sum(5)(-1)(2) == 6", function(){
+ assert.equal(6, sum(5)(-1)(2));
+ });
+
+ it("sum(6)(-1)(-2)(-3) == 0", function(){
+ assert.equal(0, sum(6)(-1)(-2)(-3));
+ });
+
+ it("sum(0)(1)(2)(3)(4)(5) == 15", function(){
+ assert.equal(15, sum(0)(1)(2)(3)(4)(5));
+ });
+});
+
diff --git a/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/solution.md b/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/solution.md
index 5c93269123..e97039f729 100644
--- a/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/solution.md
+++ b/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/solution.md
@@ -5,7 +5,7 @@
Now the code:
-```js run
+```js demo run
function sum(a) {
let currentSum = a;
@@ -52,4 +52,4 @@ function f(b) {
}
```
-This `f` will be used in the next call, again return itself, so many times as needed. Then, when used as a number or a string -- the `toString` returns the `currentSum`. We could also use `Symbol.toPrimitive` or `valueOf` here for the conversion.
+This `f` will be used in the next call, again return itself, as many times as needed. Then, when used as a number or a string -- the `toString` returns the `currentSum`. We could also use `Symbol.toPrimitive` or `valueOf` here for the conversion.
diff --git a/1-js/06-advanced-functions/06-function-object/article.md b/1-js/06-advanced-functions/06-function-object/article.md
index fb9a579823..8419ae7630 100644
--- a/1-js/06-advanced-functions/06-function-object/article.md
+++ b/1-js/06-advanced-functions/06-function-object/article.md
@@ -1,20 +1,20 @@
# Function object, NFE
-As we already know, functions in JavaScript are values.
+As we already know, a function in JavaScript is a value.
-Every value in JavaScript has the type. What type of value is a function?
+Every value in JavaScript has a type. What type is a function?
-In JavaScript, a function is an object.
+In JavaScript, functions are objects.
A good way to imagine functions is as callable "action objects". We can not only call them, but also treat them as objects: add/remove properties, pass by reference etc.
## The "name" property
-Function objects contain few sometimes-useable properties.
+Function objects contain some useable properties.
-For instance, a function name is accessible as the "name" property:
+For instance, a function's name is accessible as the "name" property:
```js run
function sayHi() {
@@ -24,17 +24,17 @@ function sayHi() {
alert(sayHi.name); // sayHi
```
-What's more funny, the name-assigning logic is smart. It also sticks the right name to function that are used in assignments:
+What's kind of funny, the name-assigning logic is smart. It also assigns the correct name to a function even if it's created without one, and then immediately assigned:
```js run
let sayHi = function() {
alert("Hi");
-}
+};
-alert(sayHi.name); // sayHi (works!)
+alert(sayHi.name); // sayHi (there's a name!)
```
-Also works if the assignment is done via a default value:
+It also works if the assignment is done via a default value:
```js run
function f(sayHi = function() {}) {
@@ -65,11 +65,9 @@ alert(user.sayHi.name); // sayHi
alert(user.sayBye.name); // sayBye
```
-There's no magic though. There are cases when there's no way to figure out the right name.
-
-Then it's empty, like here:
+There's no magic though. There are cases when there's no way to figure out the right name. In that case, the name property is empty, like here:
-```js
+```js run
// function created inside array
let arr = [function() {}];
@@ -77,7 +75,7 @@ alert( arr[0].name ); //
// the engine has no way to set up the right name, so there is none
```
-In practice, most functions do have a name.
+In practice, however, most functions do have a name.
## The "length" property
@@ -95,18 +93,18 @@ alert(many.length); // 2
Here we can see that rest parameters are not counted.
-The `length` property is sometimes used for introspection in functions that operate on other functions.
+The `length` property is sometimes used for [introspection](https://en.wikipedia.org/wiki/Type_introspection) in functions that operate on other functions.
-For instance, in the code below `ask` function accepts a `question` to ask and an arbitrary number of `handler` functions to call.
+For instance, in the code below the `ask` function accepts a `question` to ask and an arbitrary number of `handler` functions to call.
-When a user answers, it calls the handlers. We can pass two kinds of handlers:
+Once a user provides their answer, the function calls the handlers. We can pass two kinds of handlers:
-- A zero-argument function, then it is only called for a positive answer.
-- A function with arguments, then it is called in any case and gets the answer.
+- A zero-argument function, which is only called when the user gives a positive answer.
+- A function with arguments, which is called in either case and returns an answer.
-The idea is that we have a simple no-arguments handler syntax for positive cases (most frequent variant), but allow to provide universal handlers as well.
+To call `handler` the right way, we examine the `handler.length` property.
-To call `handlers` the right way, we examine the `length` property:
+The idea is that we have a simple, no-arguments handler syntax for positive cases (most frequent variant), but are able to support universal handlers as well:
```js run
function ask(question, ...handlers) {
@@ -155,10 +153,10 @@ alert( `Called ${sayHi.counter} times` ); // Called 2 times
```warn header="A property is not a variable"
A property assigned to a function like `sayHi.counter = 0` does *not* define a local variable `counter` inside it. In other words, a property `counter` and a variable `let counter` are two unrelated things.
-We can treat a function as an object, store properties in it, but that has no effect on its execution. Variables never use function properties and vice versa. These are just parallel words.
+We can treat a function as an object, store properties in it, but that has no effect on its execution. Variables are not function properties and vice versa. These are just parallel worlds.
```
-Function properties can replace the closure sometimes. For instance, we can rewrite the counter example from the chapter to use a function property:
+Function properties can replace closures sometimes. For instance, we can rewrite the counter function example from the chapter to use a function property:
```js run
function makeCounter() {
@@ -181,9 +179,9 @@ alert( counter() ); // 1
The `count` is now stored in the function directly, not in its outer Lexical Environment.
-Is it worse or better than using the closure?
+Is it better or worse than using a closure?
-The main difference is that if the value of `count` lives in an outer variable, then an external code is unable to access it. Only nested functions may modify it. And if it's bound to function, then such thing is possible:
+The main difference is that if the value of `count` lives in an outer variable, then external code is unable to access it. Only nested functions may modify it. And if it's bound to a function, then such a thing is possible:
```js run
function makeCounter() {
@@ -205,11 +203,11 @@ alert( counter() ); // 10
*/!*
```
-So it depends on our aims which variant to choose.
+So the choice of implementation depends on our aims.
## Named Function Expression
-Named Function Expression or, shortly, NFE, is a term for Function Expressions that have a name.
+Named Function Expression, or NFE, is a term for Function Expressions that have a name.
For instance, let's take an ordinary Function Expression:
@@ -219,7 +217,7 @@ let sayHi = function(who) {
};
```
-...And add a name to it:
+And add a name to it:
```js
let sayHi = function *!*func*/!*(who) {
@@ -227,7 +225,7 @@ let sayHi = function *!*func*/!*(who) {
};
```
-Did we do anything sane here? What's the role of that additional `"func"` name?
+Did we achieve anything here? What's the purpose of that additional `"func"` name?
First let's note, that we still have a Function Expression. Adding the name `"func"` after `function` did not make it a Function Declaration, because it is still created as a part of an assignment expression.
@@ -243,12 +241,12 @@ let sayHi = function *!*func*/!*(who) {
sayHi("John"); // Hello, John
```
-There are two special things about the name `func`:
+There are two special things about the name `func`, that are the reasons for it:
-1. It allows to reference the function from inside itself.
+1. It allows the function to reference itself internally.
2. It is not visible outside of the function.
-For instance, the function `sayHi` below re-calls itself with `"Guest"` if no `who` is provided:
+For instance, the function `sayHi` below calls itself again with `"Guest"` if no `who` is provided:
```js run
let sayHi = function *!*func*/!*(who) {
@@ -284,7 +282,7 @@ let sayHi = function(who) {
};
```
-The problem with that code is that the value of `sayHi` may change. The function may go to another variable, and the code will start to give errors:
+The problem with that code is that `sayHi` may change in the outer code. If the function gets assigned to another variable instead, the code will start to give errors:
```js run
let sayHi = function(who) {
@@ -305,9 +303,9 @@ welcome(); // Error, the nested sayHi call doesn't work any more!
That happens because the function takes `sayHi` from its outer lexical environment. There's no local `sayHi`, so the outer variable is used. And at the moment of the call that outer `sayHi` is `null`.
-The optional name which we can put into the Function Expression is exactly meant to solve this kind of problems.
+The optional name which we can put into the Function Expression is meant to solve exactly these kinds of problems.
-Let's use it to fix the code:
+Let's use it to fix our code:
```js run
let sayHi = function *!*func*/!*(who) {
@@ -326,12 +324,12 @@ sayHi = null;
welcome(); // Hello, Guest (nested call works)
```
-Now it works, because the name `"func"` is function-local. It is not taken from outside (and not visible there). The specification guarantees that it always references the current function.
+Now it works, because the name `"func"` is function-local. It is not taken from outside (and not visible there). The specification guarantees that it will always reference the current function.
-The outer code still has it's variable `sayHi` or `welcome` later. And `func` is an "internal function name", how it calls itself privately.
+The outer code still has its variable `sayHi` or `welcome`. And `func` is an "internal function name", the way for the function to call itself reliably.
```smart header="There's no such thing for Function Declaration"
-The "internal name" feature described here is only available for Function Expressions, not to Function Declarations. For Function Declarations, there's just no syntax possibility to add a one more "internal" name.
+The "internal name" feature described here is only available for Function Expressions, not for Function Declarations. For Function Declarations, there is no syntax for adding an "internal" name.
Sometimes, when we need a reliable internal name, it's the reason to rewrite a Function Declaration to Named Function Expression form.
```
@@ -342,13 +340,14 @@ Functions are objects.
Here we covered their properties:
-- `name` -- the function name. Exists not only when given in the function definition, but also for assignments and object properties.
+- `name` -- the function name. Usually taken from the function definition, but if there's none, JavaScript tries to guess it from the context (e.g. an assignment).
- `length` -- the number of arguments in the function definition. Rest parameters are not counted.
-If the function is declared as a Function Expression (not in the main code flow), and it carries the name, then it is called Named Function Expression. The name can be used inside to reference itself, for recursive calls or such.
+If the function is declared as a Function Expression (not in the main code flow), and it carries the name, then it is called a Named Function Expression. The name can be used inside to reference itself, for recursive calls or such.
+
+Also, functions may carry additional properties. Many well-known JavaScript libraries make great use of this feature.
-Also, functions may carry additional properties. Many well-known JavaScript libraries make a great use of this feature.
+They create a "main" function and attach many other "helper" functions to it. For instance, the [jQuery](https://jquery.com) library creates a function named `$`. The [lodash](https://lodash.com) library creates a function `_`, and then adds `_.clone`, `_.keyBy` and other properties to it (see the [docs](https://lodash.com/docs) when you want to learn more about them). Actually, they do it to lessen their pollution of the global space, so that a single library gives only one global variable. That reduces the possibility of naming conflicts.
-They create a "main" function and attach many other "helper" functions to it. For instance, the [jquery](https://jquery.com) library creates a function named `$`. The [lodash](https://lodash.com) library creates a function `_`. And then adds `_.clone`, `_.keyBy` and other properties to (see the [docs](https://lodash.com/docs) when you want learn more about them). Actually, they do it to less pollute the global space, so that a single library gives only one global variable. That lowers the chance of possible naming conflicts.
So, a function can do a useful job by itself and also carry a bunch of other functionality in properties.
diff --git a/1-js/06-advanced-functions/07-new-function/article.md b/1-js/06-advanced-functions/07-new-function/article.md
index b44da63428..ffe264a4e7 100644
--- a/1-js/06-advanced-functions/07-new-function/article.md
+++ b/1-js/06-advanced-functions/07-new-function/article.md
@@ -3,27 +3,25 @@
There's one more way to create a function. It's rarely used, but sometimes there's no alternative.
-[cut]
-
-## The syntax
+## Syntax
The syntax for creating a function:
```js
-let func = new Function('a', 'b', 'return a + b');
+let func = new Function ([arg1, arg2, ...argN], functionBody);
```
-All arguments of `new Function` are strings. Parameters go first, and the body is the last.
+The function is created with the arguments `arg1...argN` and the given `functionBody`.
-For instance:
+It's easier to understand by looking at an example. Here's a function with two arguments:
```js run
-let sum = new Function('arg1', 'arg2', 'return arg1 + arg2');
+let sum = new Function('a', 'b', 'return a + b');
alert( sum(1, 2) ); // 3
```
-If there are no arguments, then there will be only body:
+And here there's a function without arguments, with only the function body:
```js run
let sayHi = new Function('alert("Hello")');
@@ -31,29 +29,30 @@ let sayHi = new Function('alert("Hello")');
sayHi(); // Hello
```
-The major difference from other ways we've seen -- the function is created literally from a string, that is passed at run time.
+The major difference from other ways we've seen is that the function is created literally from a string, that is passed at run time.
All previous declarations required us, programmers, to write the function code in the script.
-But `new Function` allows to turn any string into a function, for example we can receive a new function from the server and then execute it:
+But `new Function` allows to turn any string into a function. For example, we can receive a new function from a server and then execute it:
```js
-let str = ... receive the code from the server dynamically ...
+let str = ... receive the code from a server dynamically ...
let func = new Function(str);
func();
```
-It is used in very specific cases, like when we receive the code from the server, or to dynamically compile a function from a template. The need for that usually arises at advanced stages of development.
+It is used in very specific cases, like when we receive code from a server, or to dynamically compile a function from a template, in complex web-applications.
-## The closure
+## Closure
-Usually, a function remembers where it was born in the special property `[[Environment]]`. It references the Lexical Environment from where it's created.
+Usually, a function remembers where it was born in the special property `[[Environment]]`. It references the Lexical Environment from where it's created (we covered that in the chapter ).
-But when a function is created using `new Function`, its `[[Environment]]` references not the current Lexical Environment, but instead the global one.
+But when a function is created using `new Function`, its `[[Environment]]` is set to reference not the current Lexical Environment, but the global one.
-```js run
+So, such function doesn't have access to outer variables, only to the global ones.
+```js run
function getFunc() {
let value = "test";
@@ -69,7 +68,7 @@ getFunc()(); // error: value is not defined
Compare it with the regular behavior:
-```js run
+```js run
function getFunc() {
let value = "test";
@@ -85,55 +84,40 @@ getFunc()(); // *!*"test"*/!*, from the Lexical Environment of getFunc
This special feature of `new Function` looks strange, but appears very useful in practice.
-Imagine that we really have to create a function from the string. The code of that function is not known at the time of writing the script (that's why we don't use regular functions), but will be known in the process of execution. We may receive it from the server or from another source.
+Imagine that we must create a function from a string. The code of that function is not known at the time of writing the script (that's why we don't use regular functions), but will be known in the process of execution. We may receive it from the server or from another source.
Our new function needs to interact with the main script.
-Maybe we want it to be able to access outer local variables?
-
-But the problem is that before JavaScript is published to production, it's compressed using a *minifier* -- a special program that shrinks code by removing extra comments, spaces and -- what's important, renames local variables into shorter ones.
-
-For instance, if a function has `let userName`, minifier replaces it `let a` (or another letter if this one is occupied), and does it everywhere. That's usually a safe thing to do, because the variable is local, nothing outside the function can access it. And inside the function minifier replaces every mention of it. Minifiers are smart, they analyze the code structure, not just find-and-replace, so that's ok.
-
-...But if `new Function` could access outer variables, then it would be unable to find `userName`.
+What if it could access the outer variables?
-**Even if we could access outer lexical environment in `new Function`, we would have problems with minifiers.**
+The problem is that before JavaScript is published to production, it's compressed using a *minifier* -- a special program that shrinks code by removing extra comments, spaces and -- what's important, renames local variables into shorter ones.
-The "special feature" of `new Function` saves us from mistakes.
+For instance, if a function has `let userName`, minifier replaces it with `let a` (or another letter if this one is occupied), and does it everywhere. That's usually a safe thing to do, because the variable is local, nothing outside the function can access it. And inside the function, minifier replaces every mention of it. Minifiers are smart, they analyze the code structure, so they don't break anything. They're not just a dumb find-and-replace.
-And it enforces better code. If we need to pass something to a function, created by `new Function`, we should pass it explicitly as arguments.
+So if `new Function` had access to outer variables, it would be unable to find renamed `userName`.
-The "sum" function actually does that right:
+**If `new Function` had access to outer variables, it would have problems with minifiers.**
-```js run
-*!*
-let sum = new Function('a', 'b', ' return a + b; ');
-*/!*
+Besides, such code would be architecturally bad and prone to errors.
-let a = 1, b = 2;
-
-*!*
-// outer values are passed as arguments
-alert( sum(a, b) ); // 3
-*/!*
-```
+To pass something to a function, created as `new Function`, we should use its arguments.
## Summary
The syntax:
```js
-let func = new Function(arg1, arg2, ..., body);
+let func = new Function ([arg1, arg2, ...argN], functionBody);
```
-For historical reasons, arguments can also be given as a comma-separated list.
+For historical reasons, arguments can also be given as a comma-separated list.
-These three mean the same:
+These three declarations mean the same:
-```js
-new Function('a', 'b', ' return a + b; '); // basic syntax
-new Function('a,b', ' return a + b; '); // comma-separated
-new Function('a , b', ' return a + b; '); // comma-separated with spaces
+```js
+new Function('a', 'b', 'return a + b'); // basic syntax
+new Function('a,b', 'return a + b'); // comma-separated
+new Function('a , b', 'return a + b'); // comma-separated with spaces
```
-Functions created with `new Function`, have `[[Environment]]` referencing the global Lexical Environment, not the outer one. Hence, they can not use outer variables. But that's actually good, because it saves us from errors. Explicit parameters passing is a much better thing architecturally and has no problems with minifiers.
\ No newline at end of file
+Functions created with `new Function`, have `[[Environment]]` referencing the global Lexical Environment, not the outer one. Hence, they cannot use outer variables. But that's actually good, because it insures us from errors. Passing parameters explicitly is a much better method architecturally and causes no problems with minifiers.
diff --git a/1-js/06-advanced-functions/08-settimeout-setinterval/1-output-numbers-100ms/solution.md b/1-js/06-advanced-functions/08-settimeout-setinterval/1-output-numbers-100ms/solution.md
index 13f01debfb..b5b1da7a6a 100644
--- a/1-js/06-advanced-functions/08-settimeout-setinterval/1-output-numbers-100ms/solution.md
+++ b/1-js/06-advanced-functions/08-settimeout-setinterval/1-output-numbers-100ms/solution.md
@@ -18,7 +18,7 @@ function printNumbers(from, to) {
printNumbers(5, 10);
```
-Using recursive `setTimeout`:
+Using nested `setTimeout`:
```js run
@@ -38,5 +38,27 @@ function printNumbers(from, to) {
printNumbers(5, 10);
```
-Note that in both solutions, there is an initial delay before the first output. Sometimes we need to add a line to make the first output immediately, that's easy to do.
+Note that in both solutions, there is an initial delay before the first output. The function is called after `1000ms` the first time.
+If we also want the function to run immediately, then we can add an additional call on a separate line, like this:
+
+```js run
+function printNumbers(from, to) {
+ let current = from;
+
+ function go() {
+ alert(current);
+ if (current == to) {
+ clearInterval(timerId);
+ }
+ current++;
+ }
+
+*!*
+ go();
+*/!*
+ let timerId = setInterval(go, 1000);
+}
+
+printNumbers(5, 10);
+```
diff --git a/1-js/06-advanced-functions/08-settimeout-setinterval/1-output-numbers-100ms/task.md b/1-js/06-advanced-functions/08-settimeout-setinterval/1-output-numbers-100ms/task.md
index 87e723c67b..84bb0c39c0 100644
--- a/1-js/06-advanced-functions/08-settimeout-setinterval/1-output-numbers-100ms/task.md
+++ b/1-js/06-advanced-functions/08-settimeout-setinterval/1-output-numbers-100ms/task.md
@@ -9,5 +9,4 @@ Write a function `printNumbers(from, to)` that outputs a number every second, st
Make two variants of the solution.
1. Using `setInterval`.
-2. Using recursive `setTimeout`.
-
+2. Using nested `setTimeout`.
diff --git a/1-js/06-advanced-functions/08-settimeout-setinterval/3-rewrite-settimeout/solution.md b/1-js/06-advanced-functions/08-settimeout-setinterval/3-rewrite-settimeout/solution.md
deleted file mode 100644
index 42a6a00468..0000000000
--- a/1-js/06-advanced-functions/08-settimeout-setinterval/3-rewrite-settimeout/solution.md
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-```js run
-let i = 0;
-
-let start = Date.now();
-
-let timer = setInterval(count, 0);
-
-function count() {
-
- for(let j = 0; j < 1000000; j++) {
- i++;
- }
-
- if (i == 1000000000) {
- alert("Done in " + (Date.now() - start) + 'ms');
- cancelInterval(timer);
- }
-
-}
-```
-
diff --git a/1-js/06-advanced-functions/08-settimeout-setinterval/3-rewrite-settimeout/task.md b/1-js/06-advanced-functions/08-settimeout-setinterval/3-rewrite-settimeout/task.md
deleted file mode 100644
index 3c78817017..0000000000
--- a/1-js/06-advanced-functions/08-settimeout-setinterval/3-rewrite-settimeout/task.md
+++ /dev/null
@@ -1,32 +0,0 @@
-importance: 4
-
----
-
-# Rewrite setTimeout with setInterval
-
-Here's the function that uses nested `setTimeout` to split a job into pieces.
-
-Rewrite it to `setInterval`:
-
-```js run
-let i = 0;
-
-let start = Date.now();
-
-function count() {
-
- if (i == 1000000000) {
- alert("Done in " + (Date.now() - start) + 'ms');
- } else {
- setTimeout(count, 0);
- }
-
- // a piece of heavy job
- for(let j = 0; j < 1000000; j++) {
- i++;
- }
-
-}
-
-count();
-```
diff --git a/1-js/06-advanced-functions/08-settimeout-setinterval/4-settimeout-result/task.md b/1-js/06-advanced-functions/08-settimeout-setinterval/4-settimeout-result/task.md
index faca460001..667c8ffa6f 100644
--- a/1-js/06-advanced-functions/08-settimeout-setinterval/4-settimeout-result/task.md
+++ b/1-js/06-advanced-functions/08-settimeout-setinterval/4-settimeout-result/task.md
@@ -6,14 +6,14 @@ importance: 5
In the code below there's a `setTimeout` call scheduled, then a heavy calculation is run, that takes more than 100ms to finish.
-When the scheduled function will run?
+When will the scheduled function run?
1. After the loop.
2. Before the loop.
3. In the beginning of the loop.
-What `alert` is going to show?
+What is `alert` going to show?
```js
let i = 0;
diff --git a/1-js/06-advanced-functions/08-settimeout-setinterval/article.md b/1-js/06-advanced-functions/08-settimeout-setinterval/article.md
index 1cb92015eb..f969599884 100644
--- a/1-js/06-advanced-functions/08-settimeout-setinterval/article.md
+++ b/1-js/06-advanced-functions/08-settimeout-setinterval/article.md
@@ -4,20 +4,17 @@ We may decide to execute a function not right now, but at a certain time later.
There are two methods for it:
-- `setTimeout` allows to run a function once after the interval of time.
-- `setInterval` allows to run a function regularly with the interval between the runs.
+- `setTimeout` allows us to run a function once after the interval of time.
+- `setInterval` allows us to run a function repeatedly, starting after the interval of time, then repeating continuously at that interval.
-These methods are not a part of JavaScript specification. But most environments have the internal scheduler and provide these methods. In particular, they are supported in all browsers and Node.JS.
-
-
-[cut]
+These methods are not a part of JavaScript specification. But most environments have the internal scheduler and provide these methods. In particular, they are supported in all browsers and Node.js.
## setTimeout
The syntax:
```js
-let timerId = setTimeout(func|code, delay[, arg1, arg2...])
+let timerId = setTimeout(func|code, [delay], [arg1], [arg2], ...)
```
Parameters:
@@ -27,10 +24,10 @@ Parameters:
Usually, that's a function. For historical reasons, a string of code can be passed, but that's not recommended.
`delay`
-: The delay before run, in milliseconds (1000 ms = 1 second).
+: The delay before run, in milliseconds (1000 ms = 1 second), by default 0.
`arg1`, `arg2`...
-: Arguments for the function (not supported in IE9-)
+: Arguments for the function
For instance, this code calls `sayHi()` after one second:
@@ -64,7 +61,7 @@ So, this will also work:
setTimeout("alert('Hello')", 1000);
```
-But using strings is not recommended, use functions instead of them, like this:
+But using strings is not recommended, use arrow functions instead of them, like this:
```js run no-beautify
setTimeout(() => alert('Hello'), 1000);
@@ -77,7 +74,7 @@ Novice developers sometimes make a mistake by adding brackets `()` after the fun
// wrong!
setTimeout(sayHi(), 1000);
```
-That doesn't work, because `setTimeout` expects a reference to function. And here `sayHi()` runs the function, and the *result of its execution* is passed to `setTimeout`. In our case the result of `sayHi()` is `undefined` (the function returns nothing), so nothing is scheduled.
+That doesn't work, because `setTimeout` expects a reference to a function. And here `sayHi()` runs the function, and the *result of its execution* is passed to `setTimeout`. In our case the result of `sayHi()` is `undefined` (the function returns nothing), so nothing is scheduled.
````
### Canceling with clearTimeout
@@ -91,7 +88,7 @@ let timerId = setTimeout(...);
clearTimeout(timerId);
```
-In the code below we schedule the function and then cancel it (changed our mind). As a result, nothing happens:
+In the code below, we schedule the function and then cancel it (changed our mind). As a result, nothing happens:
```js run no-beautify
let timerId = setTimeout(() => alert("never happens"), 1000);
@@ -101,18 +98,18 @@ clearTimeout(timerId);
alert(timerId); // same identifier (doesn't become null after canceling)
```
-As we can see from `alert` output, in a browser the timer identifier is a number. In other environments, that can be something else. For instance, Node.JS returns a timer object with additional methods.
+As we can see from `alert` output, in a browser the timer identifier is a number. In other environments, this can be something else. For instance, Node.js returns a timer object with additional methods.
Again, there is no universal specification for these methods, so that's fine.
-For browsers, timers are described in the [timers section](https://www.w3.org/TR/html5/webappapis.html#timers) of HTML5 standard.
+For browsers, timers are described in the [timers section](https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timers) of HTML Living Standard.
## setInterval
-Method `setInterval` has the same syntax as `setTimeout`:
+The `setInterval` method has the same syntax as `setTimeout`:
```js
-let timerId = setInterval(func|code, delay[, arg1, arg2...])
+let timerId = setInterval(func|code, [delay], [arg1], [arg2], ...)
```
All arguments have the same meaning. But unlike `setTimeout` it runs the function not only once, but regularly after the given interval of time.
@@ -129,17 +126,17 @@ let timerId = setInterval(() => alert('tick'), 2000);
setTimeout(() => { clearInterval(timerId); alert('stop'); }, 5000);
```
-```smart header="Modal windows freeze time in Chrome/Opera/Safari"
-In browsers IE and Firefox the internal timer continues "ticking" while showing `alert/confirm/prompt`, but in Chrome, Opera and Safari the internal timer becomes "frozen".
+```smart header="Time goes on while `alert` is shown"
+In most browsers, including Chrome and Firefox the internal timer continues "ticking" while showing `alert/confirm/prompt`.
-So if you run the code above and don't dismiss the `alert` window for some time, then in Firefox/IE next `alert` will be shown immediately as you do it (2 seconds passed from the previous invocation), and in Chrome/Opera/Safari -- after 2 more seconds (timer did not tick during the `alert`).
+So if you run the code above and don't dismiss the `alert` window for some time, then the next `alert` will be shown immediately as you do it. The actual interval between alerts will be shorter than 2 seconds.
```
-## Recursive setTimeout
+## Nested setTimeout
There are two ways of running something regularly.
-One is `setInterval`. The other one is a recursive `setTimeout`, like this:
+One is `setInterval`. The other one is a nested `setTimeout`, like this:
```js
/** instead of:
@@ -154,11 +151,11 @@ let timerId = setTimeout(function tick() {
}, 2000);
```
-The `setTimeout` above schedules next call right at the end of the current one `(*)`.
+The `setTimeout` above schedules the next call right at the end of the current one `(*)`.
-Recursive `setTimeout` is more flexible method than `setInterval`. This way the next call may be scheduled differently, depending on the results of the current one.
+The nested `setTimeout` is a more flexible method than `setInterval`. This way the next call may be scheduled differently, depending on the results of the current one.
-For instance, we need to write a service that each 5 seconds sends a request to server asking for data, but in case the server is overloaded, it should increase the interval to 10, 20, 40 seconds...
+For instance, we need to write a service that sends a request to the server every 5 seconds asking for data, but in case the server is overloaded, it should increase the interval to 10, 20, 40 seconds...
Here's the pseudocode:
```js
@@ -172,60 +169,60 @@ let timerId = setTimeout(function request() {
delay *= 2;
}
- timerId = setTimeout(tick, delay);
+ timerId = setTimeout(request, delay);
}, delay);
```
-And if we regulary have CPU-hungry tasks, then we can measure the time taken by the execution and plan the next call sooner or later.
+And if the functions that we're scheduling are CPU-hungry, then we can measure the time taken by the execution and plan the next call sooner or later.
-**Recursive `setTimeout` guarantees a delay between the executions, `setInterval` -- does not.**
+**Nested `setTimeout` allows to set the delay between the executions more precisely than `setInterval`.**
Let's compare two code fragments. The first one uses `setInterval`:
```js
let i = 1;
setInterval(function() {
- func(i);
+ func(i++);
}, 100);
```
-The second one uses recursive `setTimeout`:
+The second one uses nested `setTimeout`:
```js
let i = 1;
setTimeout(function run() {
- func(i);
+ func(i++);
setTimeout(run, 100);
}, 100);
```
-For `setInterval` the internal scheduler will run `func(i)` every 100ms:
+For `setInterval` the internal scheduler will run `func(i++)` every 100ms:
-
+
-Did you notice?...
+Did you notice?
**The real delay between `func` calls for `setInterval` is less than in the code!**
-That's natural, because the time taken by `func` execution "consumes" a part of the interval.
+That's normal, because the time taken by `func`'s execution "consumes" a part of the interval.
-It is possible that `func` execution turns out to be longer than we expected and takes more than 100ms.
+It is possible that `func`'s execution turns out to be longer than we expected and takes more than 100ms.
-In this case the engine waits for `func` to complete, then checks the scheduler and if the time is up, then runs it again *immediately*.
+In this case the engine waits for `func` to complete, then checks the scheduler and if the time is up, runs it again *immediately*.
-In the edge case, if the function always executes longer than `delay` ms, then the calls will happen without pause at all.
+In the edge case, if the function always executes longer than `delay` ms, then the calls will happen without a pause at all.
-And here is the picture for recursive `setTimeout`:
+And here is the picture for the nested `setTimeout`:
-
+
-**Recursive `setTimeout` guarantees the fixed delay (here 100ms).**
+**The nested `setTimeout` guarantees the fixed delay (here 100ms).**
That's because a new call is planned at the end of the previous one.
-````smart header="Garbage collection"
+````smart header="Garbage collection and setInterval/setTimeout callback"
When a function is passed in `setInterval/setTimeout`, an internal reference is created to it and saved in the scheduler. It prevents the function from being garbage collected, even if there are no other references to it.
```js
@@ -233,137 +230,35 @@ When a function is passed in `setInterval/setTimeout`, an internal reference is
setTimeout(function() {...}, 100);
```
-For `setInterval` the function stays in memory until `cancelInterval` is called.
+For `setInterval` the function stays in memory until `clearInterval` is called.
-There's a side-effect. A function references the outer lexical environment, so, while it lives, outer variables live too. They may take much more memory than the function itself. So when we don't need the scheduled function any more, it's better to cancel it, even if it's very small.
+There's a side effect. A function references the outer lexical environment, so, while it lives, outer variables live too. They may take much more memory than the function itself. So when we don't need the scheduled function anymore, it's better to cancel it, even if it's very small.
````
-## setTimeout(...,0)
+## Zero delay setTimeout
-There's a special use case: `setTimeout(func, 0)`.
+There's a special use case: `setTimeout(func, 0)`, or just `setTimeout(func)`.
-This schedules the execution of `func` as soon as possible. But scheduler will invoke it only after the current code is complete.
+This schedules the execution of `func` as soon as possible. But the scheduler will invoke it only after the currently executing script is complete.
-So the function is scheduled to run "right after" the current code. In other words, *asynchronously*.
+So the function is scheduled to run "right after" the current script.
For instance, this outputs "Hello", then immediately "World":
```js run
-setTimeout(() => alert("World"), 0);
+setTimeout(() => alert("World"));
alert("Hello");
```
-The first line "puts the call into calendar after 0ms". But the scheduler will only "check the calendar" after the current code is complete, so `"Hello"` is first, and `"World"` -- after it.
-
-### Splitting CPU-hungry tasks
-
-There's a trick to split CPU-hungry task using `setTimeout`.
-
-For instance, syntax highlighting script (used to colorize code examples on this page) is quite CPU-heavy. To hightlight the code, it performs the analysis, creates many colored elements, adds them to the document -- for a big text that takes a lot. It may even cause the browser to "hang", that's unacceptable.
-
-So we can split the long text to pieces. First 100 lines, then plan another 100 lines using `setTimeout(...,0)`, and so on.
-
-For clarity, let's take a simpler example for consideration. We have a function to count from `1` to `1000000000`.
-
-If you run it, the CPU will hang. For server-side JS that's clearly noticeable, and if you are running it in-browser, then try to click other buttons on the page -- you'll see that whole JavaScript actually is paused, no other actions work until it finishes.
-
-```js run
-let i = 0;
-
-let start = Date.now();
-
-function count() {
-
- // do a heavy job
- for(let j = 0; j < 1e9; j++) {
- i++;
- }
-
- alert("Done in " + (Date.now() - start) + 'ms');
-}
-
-count();
-```
-
-The browser may even show "the script takes too long" warning (but hopefully won't, the number is not very big).
+The first line "puts the call into calendar after 0ms". But the scheduler will only "check the calendar" after the current script is complete, so `"Hello"` is first, and `"World"` -- after it.
-Let's split the job using the nested `setTimeout`:
+There are also advanced browser-related use cases of zero-delay timeout, that we'll discuss in the chapter .
-```js run
-let i = 0;
-
-let start = Date.now();
-
-function count() {
-
- // do a piece of the heavy job (*)
- do {
- i++;
- } while (i % 1e6 != 0);
-
- if (i == 1e9) {
- alert("Done in " + (Date.now() - start) + 'ms');
- } else {
- setTimeout(count, 0); // schedule the new call (**)
- }
-
-}
-
-count();
-```
-
-Now the browser UI is fully functional during the "counting" process.
-
-We do a part of the job `(*)`:
-
-1. First run: `i=1...1000000`.
-2. Second run: `i=1000001..2000000`.
-3. ...and so on, the `while` checks if `i` is evenly divided by `100000`.
-
-Then the next call is scheduled in `(*)` if we're not done yet.
+````smart header="Zero delay is in fact not zero (in a browser)"
+In the browser, there's a limitation of how often nested timers can run. The [HTML Living Standard](https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timers) says: "after five nested timers, the interval is forced to be at least 4 milliseconds.".
-Pauses between `count` executions provide just enough "breath" for the JavaScript engine to do something else, to react on other user actions.
-
-The notable thing is that both variants: with and without splitting the job by `setInterval` -- are comparable in speed. There's no much difference in the overall counting time.
-
-To make them closer let's make an improvement.
-
-We'll move the scheduling in the beginning of the `count()`:
-
-```js run
-let i = 0;
-
-let start = Date.now();
-
-function count() {
-
- // move the scheduling at the beginning
- if (i < 1e9 - 1e6) {
- setTimeout(count, 0); // schedule the new call
- }
-
- do {
- i++;
- } while (i % 1e6 != 0);
-
- if (i == 1e9) {
- alert("Done in " + (Date.now() - start) + 'ms');
- }
-
-}
-
-count();
-```
-
-Now when we start to `count()` and know that we'll need to `count()` more -- we schedule that immediately, before doing the job.
-
-If you run it, easy to notice that it takes significantly less time.
-
-````smart header="Minimal delay of nested timers in-browser"
-In the browser, there's a limitation of how often nested timers can run. The [HTML5 standard](https://www.w3.org/TR/html5/webappapis.html#timers) says: "after five nested timers..., the interval is forced to be at least four milliseconds.".
-
-Let's demonstrate what it means by the example below. The `setTimeout` call in it re-schedules itself after `0ms`. Each call remembers the real time from the previous one in the `times` array. What the real delays look like? Let's see:
+Let's demonstrate what it means with the example below. The `setTimeout` call in it re-schedules itself with zero delay. Each call remembers the real time from the previous one in the `times` array. What do the real delays look like? Let's see:
```js run
let start = Date.now();
@@ -373,92 +268,35 @@ setTimeout(function run() {
times.push(Date.now() - start); // remember delay from the previous call
if (start + 100 < Date.now()) alert(times); // show the delays after 100ms
- else setTimeout(run, 0); // else re-schedule
-}, 0);
+ else setTimeout(run); // else re-schedule
+});
// an example of the output:
// 1,1,1,1,9,15,20,24,30,35,40,45,50,55,59,64,70,75,80,85,90,95,100
```
-First timers run immediately (just as written in the spec), and then the delay comes into play and we see `9, 15, 20, 24...`.
+First timers run immediately (just as written in the spec), and then we see `9, 15, 20, 24...`. The 4+ ms obligatory delay between invocations comes into play.
+
+The similar thing happens if we use `setInterval` instead of `setTimeout`: `setInterval(f)` runs `f` few times with zero-delay, and afterwards with 4+ ms delay.
That limitation comes from ancient times and many scripts rely on it, so it exists for historical reasons.
-For server-side JavaScript, that limitation does not exist, and there exist other ways to schedule an immediate asynchronous job, like [process.nextTick](https://nodejs.org/api/process.html) and [setImmediate](https://nodejs.org/api/timers.html) for Node.JS. So the notion is browser-specific only.
+For server-side JavaScript, that limitation does not exist, and there exist other ways to schedule an immediate asynchronous job, like [setImmediate](https://nodejs.org/api/timers.html#timers_setimmediate_callback_args) for Node.js. So this note is browser-specific.
````
-### Allowing the browser to render
-
-Another benefit for in-browser scripts is that they can show a progress bar or something to the user. That's because the browser usually does all "repainting" after the script is complete.
-
-So if we do a single huge function then even if it changes something, the changes are not reflected in the document till it finishes.
-
-Here's the demo:
-```html run
-
-
-
-```
-
-If you run it, the changes to `i` will show up after the whole count finishes.
-
-And if we use `setTimeout` to split it into pieces then changes are applied in-between the runs, so this looks better:
-
-```html run
-
-
-
-```
-
-Now the `
` shows increasing values of `i`.
-
## Summary
-- Methods `setInterval(func, delay, ...args)` and `setTimeout(func, delay, ...args)` allow to run the `func` regularly/once after `delay` milliseconds.
-- To cancel the execution, we should call `clearInterval/clearTimeout` with the value returned by `setInterval/setTimeout`.
-- Nested `setTimeout` calls is a more flexible alternative to `setInterval`. Also they can guarantee the minimal time *between* the executions.
-- Zero-timeout scheduling `setTimeout(...,0)` is used to schedule the call "as soon as possible, but after the current code is complete".
-
-Some use cases of `setTimeout(...,0)`:
-- To split CPU-hungry tasks into pieces, so that the script doesn't "hang"
-- To let the browser do something else while the process is going on (paint the progress bar).
+- Methods `setTimeout(func, delay, ...args)` and `setInterval(func, delay, ...args)` allow us to run the `func` once/regularly after `delay` milliseconds.
+- To cancel the execution, we should call `clearTimeout/clearInterval` with the value returned by `setTimeout/setInterval`.
+- Nested `setTimeout` calls are a more flexible alternative to `setInterval`, allowing us to set the time *between* executions more precisely.
+- Zero delay scheduling with `setTimeout(func, 0)` (the same as `setTimeout(func)`) is used to schedule the call "as soon as possible, but after the current script is complete".
+- The browser limits the minimal delay for five or more nested calls of `setTimeout` or for `setInterval` (after 5th call) to 4ms. That's for historical reasons.
-Please note that all scheduling methods do not *guarantee* the exact delay. We should not rely on that in the scheduled code.
+Please note that all scheduling methods do not *guarantee* the exact delay.
For example, the in-browser timer may slow down for a lot of reasons:
- The CPU is overloaded.
- The browser tab is in the background mode.
-- The laptop is on battery.
+- The laptop is on battery saving mode.
-All that may decrease the minimal timer resolution (the minimal delay) to 300ms or even 1000ms depending on the browser and settings.
+All that may increase the minimal timer resolution (the minimal delay) to 300ms or even 1000ms depending on the browser and OS-level performance settings.
diff --git a/1-js/06-advanced-functions/08-settimeout-setinterval/setinterval-interval.png b/1-js/06-advanced-functions/08-settimeout-setinterval/setinterval-interval.png
deleted file mode 100644
index 060b2c293b..0000000000
Binary files a/1-js/06-advanced-functions/08-settimeout-setinterval/setinterval-interval.png and /dev/null differ
diff --git a/1-js/06-advanced-functions/08-settimeout-setinterval/setinterval-interval.svg b/1-js/06-advanced-functions/08-settimeout-setinterval/setinterval-interval.svg
new file mode 100644
index 0000000000..bce7d6a843
--- /dev/null
+++ b/1-js/06-advanced-functions/08-settimeout-setinterval/setinterval-interval.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/06-advanced-functions/08-settimeout-setinterval/setinterval-interval@2x.png b/1-js/06-advanced-functions/08-settimeout-setinterval/setinterval-interval@2x.png
deleted file mode 100644
index 4071849cd5..0000000000
Binary files a/1-js/06-advanced-functions/08-settimeout-setinterval/setinterval-interval@2x.png and /dev/null differ
diff --git a/1-js/06-advanced-functions/08-settimeout-setinterval/settimeout-interval.png b/1-js/06-advanced-functions/08-settimeout-setinterval/settimeout-interval.png
deleted file mode 100644
index 6c473a33cc..0000000000
Binary files a/1-js/06-advanced-functions/08-settimeout-setinterval/settimeout-interval.png and /dev/null differ
diff --git a/1-js/06-advanced-functions/08-settimeout-setinterval/settimeout-interval.svg b/1-js/06-advanced-functions/08-settimeout-setinterval/settimeout-interval.svg
new file mode 100644
index 0000000000..d6d233b2ba
--- /dev/null
+++ b/1-js/06-advanced-functions/08-settimeout-setinterval/settimeout-interval.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/06-advanced-functions/08-settimeout-setinterval/settimeout-interval@2x.png b/1-js/06-advanced-functions/08-settimeout-setinterval/settimeout-interval@2x.png
deleted file mode 100644
index dd45e324f8..0000000000
Binary files a/1-js/06-advanced-functions/08-settimeout-setinterval/settimeout-interval@2x.png and /dev/null differ
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/_js.view/solution.js b/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/_js.view/solution.js
index 9ef503703b..d5a09efb36 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/_js.view/solution.js
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/_js.view/solution.js
@@ -1,11 +1,12 @@
function spy(func) {
function wrapper(...args) {
+ // using ...args instead of arguments to store "real" array in wrapper.calls
wrapper.calls.push(args);
- return func.apply(this, arguments);
+ return func.apply(this, args);
}
wrapper.calls = [];
return wrapper;
-}
\ No newline at end of file
+}
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/_js.view/test.js b/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/_js.view/test.js
index 7e84f3c99d..5adfcb9787 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/_js.view/test.js
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/_js.view/test.js
@@ -24,7 +24,7 @@ describe("spy", function() {
let wrappedSum = spy(sum);
assert.equal(wrappedSum(1, 2), 3);
- assert(spy.calledWith(1, 2));
+ assert(sum.calledWith(1, 2));
});
@@ -36,9 +36,9 @@ describe("spy", function() {
calc.wrappedSum = spy(calc.sum);
- assert.equal(calculator.wrappedSum(1, 2), 3);
- assert(spy.calledWith(1, 2));
- assert(spy.calledOn(calculator));
+ assert.equal(calc.wrappedSum(1, 2), 3);
+ assert(calc.sum.calledWith(1, 2));
+ assert(calc.sum.calledOn(calc));
});
-});
\ No newline at end of file
+});
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/solution.md b/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/solution.md
index 4a79d3e118..0c8a211b49 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/solution.md
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/solution.md
@@ -1 +1 @@
-Here we can use `log.push(args)` to store all arguments in the log and `f.apply(this, args)` to forward the call.
+The wrapper returned by `spy(f)` should store all arguments and then use `f.apply` to forward the call.
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/task.md b/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/task.md
index e4a30cb83d..a3843107c9 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/task.md
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/task.md
@@ -22,9 +22,9 @@ work = spy(work);
work(1, 2); // 3
work(4, 5); // 9
-for(let args of work.calls) {
+for (let args of work.calls) {
alert( 'call:' + args.join() ); // "call:1,2", "call:4,5"
}
```
-P.S. That decorator is sometimes useful for unit-testing, it's advanced form is `sinon.spy` in [Sinon.JS](http://sinonjs.org/) library.
+P.S. That decorator is sometimes useful for unit-testing. Its advanced form is `sinon.spy` in [Sinon.JS](http://sinonjs.org/) library.
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/02-delay/solution.md b/1-js/06-advanced-functions/09-call-apply-decorators/02-delay/solution.md
index 44b5024e18..24bb4d4484 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/02-delay/solution.md
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/02-delay/solution.md
@@ -1,6 +1,6 @@
The solution:
-```js
+```js run demo
function delay(f, ms) {
return function() {
@@ -8,20 +8,25 @@ function delay(f, ms) {
};
}
+
+let f1000 = delay(alert, 1000);
+
+f1000("test"); // shows "test" after 1000ms
```
Please note how an arrow function is used here. As we know, arrow functions do not have own `this` and `arguments`, so `f.apply(this, arguments)` takes `this` and `arguments` from the wrapper.
-If we pass a regular function, `setTimeout` would call it without arguments and `this=window` (in-browser), so we'd need to write a bit more code to pass them from the wrapper:
+If we pass a regular function, `setTimeout` would call it without arguments and `this=window` (assuming we're in the browser).
+
+We still can pass the right `this` by using an intermediate variable, but that's a little bit more cumbersome:
```js
function delay(f, ms) {
- // added variables to pass this and arguments from the wrapper inside setTimeout
return function(...args) {
- let savedThis = this;
+ let savedThis = this; // store this into an intermediate variable
setTimeout(function() {
- f.apply(savedThis, args);
+ f.apply(savedThis, args); // use it here
}, ms);
};
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/_js.view/solution.js b/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/_js.view/solution.js
index 065a77d1f9..661dd0cf41 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/_js.view/solution.js
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/_js.view/solution.js
@@ -1,15 +1,7 @@
-function debounce(f, ms) {
-
- let isCooldown = false;
-
+function debounce(func, ms) {
+ let timeout;
return function() {
- if (isCooldown) return;
-
- f.apply(this, arguments);
-
- isCooldown = true;
-
- setTimeout(() => isCooldown = false, ms);
+ clearTimeout(timeout);
+ timeout = setTimeout(() => func.apply(this, arguments), ms);
};
-
-}
\ No newline at end of file
+}
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/_js.view/test.js b/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/_js.view/test.js
index 16dc171e1a..750e649f83 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/_js.view/test.js
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/_js.view/test.js
@@ -1,41 +1,48 @@
-describe("debounce", function() {
- before(function() {
+describe('debounce', function () {
+ before(function () {
this.clock = sinon.useFakeTimers();
});
- after(function() {
+ after(function () {
this.clock.restore();
});
- it("calls the function at maximum once in ms milliseconds", function() {
- let log = '';
+ it('for one call - runs it after given ms', function () {
+ const f = sinon.spy();
+ const debounced = debounce(f, 1000);
- function f(a) {
- log += a;
- }
+ debounced('test');
+ assert(f.notCalled, 'not called immediately');
+ this.clock.tick(1000);
+ assert(f.calledOnceWith('test'), 'called after 1000ms');
+ });
- f = debounce(f, 1000);
+ it('for 3 calls - runs the last one after given ms', function () {
+ const f = sinon.spy();
+ const debounced = debounce(f, 1000);
- f(1); // runs at once
- f(2); // ignored
+ debounced('a');
+ setTimeout(() => debounced('b'), 200); // ignored (too early)
+ setTimeout(() => debounced('c'), 500); // runs (1000 ms passed)
+ this.clock.tick(1000);
- setTimeout(() => f(3), 100); // ignored (too early)
- setTimeout(() => f(4), 1100); // runs (1000 ms passed)
- setTimeout(() => f(5), 1500); // ignored (less than 1000 ms from the last run)
+ assert(f.notCalled, 'not called after 1000ms');
- this.clock.tick(5000);
- assert.equal(log, "14");
+ this.clock.tick(500);
+
+ assert(f.calledOnceWith('c'), 'called after 1500ms');
});
- it("keeps the context of the call", function() {
+ it('keeps the context of the call', function () {
let obj = {
f() {
assert.equal(this, obj);
- }
+ },
};
obj.f = debounce(obj.f, 1000);
- obj.f("test");
+ obj.f('test');
+ this.clock.tick(5000);
});
-
-});
\ No newline at end of file
+
+});
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/debounce.svg b/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/debounce.svg
new file mode 100644
index 0000000000..e624ce0203
--- /dev/null
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/debounce.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/debounce.view/index.html b/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/debounce.view/index.html
new file mode 100644
index 0000000000..e3b4d5842f
--- /dev/null
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/debounce.view/index.html
@@ -0,0 +1,24 @@
+
+
+
+Function handler is called on this input:
+
+
+
+
+
+Debounced function debounce(handler, 1000) is called on this input:
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/solution.md b/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/solution.md
index 1516aca350..83e75f3158 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/solution.md
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/solution.md
@@ -1,30 +1,13 @@
-
-
-```js run no-beautify
-function debounce(f, ms) {
-
- let isCooldown = false;
-
+```js demo
+function debounce(func, ms) {
+ let timeout;
return function() {
- if (isCooldown) return;
-
- f.apply(this, arguments);
-
- isCooldown = true;
-
- setTimeout(() => isCooldown = false, ms);
+ clearTimeout(timeout);
+ timeout = setTimeout(() => func.apply(this, arguments), ms);
};
-
}
-```
-The call to `debounce` returns a wrapper. There may be two states:
-
-- `isCooldown = false` -- ready to run.
-- `isCooldown = true` -- waiting for the timeout.
-
-In the first call `isCooldown` is falsy, so the call proceeds, and the state changes to `true`.
+```
-While `isCooldown` is true, all other calls are ignored.
+A call to `debounce` returns a wrapper. When called, it schedules the original function call after given `ms` and cancels the previous such timeout.
-Then `setTimeout` reverts it to `false` after the given delay.
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/task.md b/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/task.md
index 466c6bc3f7..5b0fcc5f87 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/task.md
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/task.md
@@ -4,21 +4,48 @@ importance: 5
# Debounce decorator
-The result of `debounce(f, ms)` decorator should be a wrapper that passes the call to `f` at maximum once per `ms` milliseconds.
+The result of `debounce(f, ms)` decorator is a wrapper that suspends calls to `f` until there's `ms` milliseconds of inactivity (no calls, "cooldown period"), then invokes `f` once with the latest arguments.
-In other words, when we call a "debounced" function, it guarantees that all other future in the closest `ms` milliseconds will be ignored.
+In other words, `debounce` is like a secretary that accepts "phone calls", and waits until there's `ms` milliseconds of being quiet. And only then it transfers the latest call information to "the boss" (calls the actual `f`).
-For instance:
+For instance, we had a function `f` and replaced it with `f = debounce(f, 1000)`.
-```js no-beautify
-let f = debounce(alert, 1000);
+Then if the wrapped function is called at 0ms, 200ms and 500ms, and then there are no calls, then the actual `f` will be only called once, at 1500ms. That is: after the cooldown period of 1000ms from the last call.
-f(1); // runs immediately
-f(2); // ignored
+
-setTimeout( () => f(3), 100); // ignored ( only 100 ms passed )
-setTimeout( () => f(4), 1100); // runs
-setTimeout( () => f(5), 1500); // ignored (less than 1000 ms from the last run)
+...And it will get the arguments of the very last call, other calls are ignored.
+
+Here's the code for it (uses the debounce decorator from the [Lodash library](https://lodash.com/docs/4.17.15#debounce)):
+
+```js
+let f = _.debounce(alert, 1000);
+
+f("a");
+setTimeout( () => f("b"), 200);
+setTimeout( () => f("c"), 500);
+// debounced function waits 1000ms after the last call and then runs: alert("c")
+```
+
+Now a practical example. Let's say, the user types something, and we'd like to send a request to the server when the input is finished.
+
+There's no point in sending the request for every character typed. Instead we'd like to wait, and then process the whole result.
+
+In a web-browser, we can setup an event handler -- a function that's called on every change of an input field. Normally, an event handler is called very often, for every typed key. But if we `debounce` it by 1000ms, then it will be only called once, after 1000ms after the last input.
+
+```online
+
+In this live example, the handler puts the result into a box below, try it:
+
+[iframe border=1 src="http://github.com/debounce" height=200]
+
+See? The second input calls the debounced function, so its content is processed after 1000ms from the last input.
```
-In practice `debounce` is useful for functions that retrieve/update something when we know that nothing new can be done in such a short period of time, so it's better not to waste resources.
\ No newline at end of file
+So, `debounce` is a great way to process a sequence of events: be it a sequence of key presses, mouse movements or something else.
+
+It waits the given time after the last call, and then runs its function, that can process the result.
+
+The task is to implement `debounce` decorator.
+
+Hint: that's just a few lines if you think about it :)
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/_js.view/test.js b/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/_js.view/test.js
index 5339c8d117..e671438f6f 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/_js.view/test.js
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/_js.view/test.js
@@ -7,8 +7,8 @@ describe("throttle(f, 1000)", function() {
}
before(function() {
- f1000 = throttle(f, 1000);
this.clock = sinon.useFakeTimers();
+ f1000 = throttle(f, 1000);
});
it("the first call runs now", function() {
@@ -44,4 +44,20 @@ describe("throttle(f, 1000)", function() {
this.clock.restore();
});
-});
\ No newline at end of file
+});
+
+describe('throttle', () => {
+
+ it('runs a forwarded call once', done => {
+ let log = '';
+ const f = str => log += str;
+ const f10 = throttle(f, 10);
+ f10('once');
+
+ setTimeout(() => {
+ assert.equal(log, 'once');
+ done();
+ }, 20);
+ });
+
+});
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/solution.md b/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/solution.md
index 372ebedd1e..6950664be1 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/solution.md
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/solution.md
@@ -1,4 +1,4 @@
-```js
+```js demo
function throttle(func, ms) {
let isThrottled = false,
@@ -12,11 +12,10 @@ function throttle(func, ms) {
savedThis = this;
return;
}
+ isThrottled = true;
func.apply(this, arguments); // (1)
- isThrottled = true;
-
setTimeout(function() {
isThrottled = false; // (3)
if (savedArgs) {
@@ -33,7 +32,7 @@ function throttle(func, ms) {
A call to `throttle(func, ms)` returns `wrapper`.
1. During the first call, the `wrapper` just runs `func` and sets the cooldown state (`isThrottled = true`).
-2. In this state all calls memorized in `savedArgs/savedThis`. Please note that both the context and the arguments are equally important and should be memorized. We need them simultaneously to reproduce the call.
-3. ...Then after `ms` milliseconds pass, `setTimeout` triggers. The cooldown state is removed (`isThrottled = false`). And if we had ignored calls, then `wrapper` is executed with last memorized arguments and context.
+2. In this state all calls are memorized in `savedArgs/savedThis`. Please note that both the context and the arguments are equally important and should be memorized. We need them simultaneously to reproduce the call.
+3. After `ms` milliseconds pass, `setTimeout` triggers. The cooldown state is removed (`isThrottled = false`) and, if we had ignored calls, `wrapper` is executed with the last memorized arguments and context.
The 3rd step runs not `func`, but `wrapper`, because we not only need to execute `func`, but once again enter the cooldown state and setup the timeout to reset it.
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/task.md b/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/task.md
index 4af0d54c92..cbd4731960 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/task.md
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/task.md
@@ -4,35 +4,40 @@ importance: 5
# Throttle decorator
-Create a "throttling" decorator `throttle(f, ms)` -- that returns a wrapper, passing the call to `f` at maximum once per `ms` milliseconds. Those calls that fall into the "cooldown" period, are ignored.
+Create a "throttling" decorator `throttle(f, ms)` -- that returns a wrapper.
-**The difference with `debounce` -- if an ignored call is the last during the cooldown, then it executes at the end of the delay.**
+When it's called multiple times, it passes the call to `f` at maximum once per `ms` milliseconds.
+
+Compared to the debounce decorator, the behavior is completely different:
+- `debounce` runs the function once after the "cooldown" period. Good for processing the final result.
+- `throttle` runs it not more often than given `ms` time. Good for regular updates that shouldn't be very often.
+
+In other words, `throttle` is like a secretary that accepts phone calls, but bothers the boss (calls the actual `f`) not more often than once per `ms` milliseconds.
Let's check the real-life application to better understand that requirement and to see where it comes from.
**For instance, we want to track mouse movements.**
-In browser we can setup a function to run at every mouse micro-movement and get the pointer location as it moves. During an active mouse usage, this function usually runs very frequently, can be something like 100 times per second (every 10 ms).
-
-**The tracking function should update some information on the web-page.**
+In a browser we can setup a function to run at every mouse movement and get the pointer location as it moves. During an active mouse usage, this function usually runs very frequently, can be something like 100 times per second (every 10 ms).
+**We'd like to update some information on the web-page when the pointer moves.**
-Updating function `update()` is too heavy to do it on every micro-movement. There is also no sense in making it more often than once per 100ms.
+...But updating function `update()` is too heavy to do it on every micro-movement. There is also no sense in updating more often than once per 100ms.
-So we'll assign `throttle(update, 100)` as the function to run on each mouse move instead of the original `update()`. The decorator will be called often, but `update()` will be called at maximum once per 100ms.
+So we'll wrap it into the decorator: use `throttle(update, 100)` as the function to run on each mouse move instead of the original `update()`. The decorator will be called often, but forward the call to `update()` at maximum once per 100ms.
Visually, it will look like this:
-1. For the first mouse movement the decorated variant passes the call to `update`. That's important, the user sees our reaction to his move immediately.
+1. For the first mouse movement the decorated variant immediately passes the call to `update`. That's important, the user sees our reaction to their move immediately.
2. Then as the mouse moves on, until `100ms` nothing happens. The decorated variant ignores calls.
-3. At the end of `100ms` -- one more `update` happens with the last coordinates.
-4. Then, finally, the mouse stops somewhere. The decorated variant waits until `100ms` expire and then runs `update` runs with last coordinates. So, perhaps the most important, the final mouse coordinates are processed.
+3. At the end of `100ms` -- one more `update` happens with the last coordinates.
+4. Then, finally, the mouse stops somewhere. The decorated variant waits until `100ms` expire and then runs `update` with last coordinates. So, quite important, the final mouse coordinates are processed.
A code example:
```js
function f(a) {
- console.log(a)
-};
+ console.log(a);
+}
// f1000 passes calls to f at maximum once per 1000 ms
let f1000 = throttle(f, 1000);
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/article.md b/1-js/06-advanced-functions/09-call-apply-decorators/article.md
index 707bbf5890..c5d785493c 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/article.md
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/article.md
@@ -2,15 +2,13 @@
JavaScript gives exceptional flexibility when dealing with functions. They can be passed around, used as objects, and now we'll see how to *forward* calls between them and *decorate* them.
-[cut]
-
## Transparent caching
Let's say we have a function `slow(x)` which is CPU-heavy, but its results are stable. In other words, for the same `x` it always returns the same result.
-If the function is called often, we may want to cache (remember) the results for different `x` to avoid spending extra-time on recalculations.
+If the function is called often, we may want to cache (remember) the results to avoid spending extra-time on recalculations.
-But instead of adding that functionality into `slow()` we'll create a wrapper. As we'll see, there are many benefits of doing so.
+But instead of adding that functionality into `slow()` we'll create a wrapper function, that adds caching. As we'll see, there are many benefits of doing so.
Here's the code, and explanations follow:
@@ -25,24 +23,24 @@ function cachingDecorator(func) {
let cache = new Map();
return function(x) {
- if (cache.has(x)) { // if the result is in the map
- return cache.get(x); // return it
+ if (cache.has(x)) { // if there's such key in cache
+ return cache.get(x); // read the result from it
}
- let result = func(x); // otherwise call func
+ let result = func(x); // otherwise call func
- cache.set(x, result); // and cache (remember) the result
+ cache.set(x, result); // and cache (remember) the result
return result;
};
}
slow = cachingDecorator(slow);
-alert( slow(1) ); // slow(1) is cached
-alert( "Again: " + slow(1) ); // the same
+alert( slow(1) ); // slow(1) is cached and the result returned
+alert( "Again: " + slow(1) ); // slow(1) result returned from cache
-alert( slow(2) ); // slow(2) is cached
-alert( "Again: " + slow(2) ); // the same as the previous line
+alert( slow(2) ); // slow(2) is cached and the result returned
+alert( "Again: " + slow(2) ); // slow(2) result returned from cache
```
In the code above `cachingDecorator` is a *decorator*: a special function that takes another function and alters its behavior.
@@ -51,26 +49,23 @@ The idea is that we can call `cachingDecorator` for any function, and it will re
By separating caching from the main function code we also keep the main code simpler.
-Now let's get into details of how it works.
-
The result of `cachingDecorator(func)` is a "wrapper": `function(x)` that "wraps" the call of `func(x)` into caching logic:
-
+
-As we can see, the wrapper returns the result of `func(x)` "as is". From an outside code, the wrapped `slow` function still does the same. It just got a caching aspect added to its behavior.
+From an outside code, the wrapped `slow` function still does the same. It just got a caching aspect added to its behavior.
To summarize, there are several benefits of using a separate `cachingDecorator` instead of altering the code of `slow` itself:
- The `cachingDecorator` is reusable. We can apply it to another function.
-- The caching logic is separate, it did not increase the complexity of `slow` itself (if there were any).
+- The caching logic is separate, it did not increase the complexity of `slow` itself (if there was any).
- We can combine multiple decorators if needed (other decorators will follow).
-
## Using "func.call" for the context
The caching decorator mentioned above is not suited to work with object methods.
-For instance, in the code below `user.format()` stops working after the decoration:
+For instance, in the code below `worker.slow()` stops working after the decoration:
```js run
// we'll make worker.slow caching
@@ -80,7 +75,7 @@ let worker = {
},
slow(x) {
- // actually, there can be a scary CPU-heavy task here
+ // scary CPU-heavy task here
alert("Called with " + x);
return x * this.someMethod(); // (*)
}
@@ -135,7 +130,7 @@ func.call(context, arg1, arg2, ...)
It runs `func` providing the first argument as `this`, and the next as the arguments.
-To put it simple, these two calls do almost the same:
+To put it simply, these two calls do almost the same:
```js
func(1, 2, 3);
func.call(obj, 1, 2, 3)
@@ -172,10 +167,8 @@ let user = { name: "John" };
say.call( user, "Hello" ); // John: Hello
```
-
In our case, we can use `call` in the wrapper to pass the context to the original function:
-
```js run
let worker = {
someMethod() {
@@ -216,7 +209,7 @@ To make it all clear, let's see more deeply how `this` is passed along:
2. So when `worker.slow(2)` is executed, the wrapper gets `2` as an argument and `this=worker` (it's the object before dot).
3. Inside the wrapper, assuming the result is not yet cached, `func.call(this, x)` passes the current `this` (`=worker`) and the current argument (`=2`) to the original method.
-## Going multi-argument with "func.apply"
+## Going multi-argument
Now let's make `cachingDecorator` even more universal. Till now it was working only with single-argument functions.
@@ -233,95 +226,19 @@ let worker = {
worker.slow = cachingDecorator(worker.slow);
```
-We have two tasks to solve here.
-
-First is how to use both arguments `min` and `max` for the key in `cache` map. Previously, for a single argument `x` we could just `cache.set(x, result)` to save the result and `cache.get(x)` to retrieve it. But now we need to remember the result for a *combination of arguments* `(min,max)`. The native `Map` takes single value only as the key.
+Previously, for a single argument `x` we could just `cache.set(x, result)` to save the result and `cache.get(x)` to retrieve it. But now we need to remember the result for a *combination of arguments* `(min,max)`. The native `Map` takes single value only as the key.
There are many solutions possible:
1. Implement a new (or use a third-party) map-like data structure that is more versatile and allows multi-keys.
2. Use nested maps: `cache.set(min)` will be a `Map` that stores the pair `(max, result)`. So we can get `result` as `cache.get(min).get(max)`.
-3. Join two values into one. In our particular case we can just use a string `"min,max"` as the `Map` key. For flexibility, we can allow to provide a *hashing function* for the decorator, that knows how to make a one value from many.
-
+3. Join two values into one. In our particular case we can just use a string `"min,max"` as the `Map` key. For flexibility, we can allow to provide a *hashing function* for the decorator, that knows how to make one value from many.
For many practical applications, the 3rd variant is good enough, so we'll stick to it.
-The second task to solve is how to pass many arguments to `func`. Currently, the wrapper `function(x)` assumes a single argument, and `func.call(this, x)` passes it.
-
-Here we can use another built-in method [func.apply](mdn:js/Function/apply).
-
-The syntax is:
-
-```js
-func.apply(context, args)
-```
-
-It runs the `func` setting `this=context` and using an array-like object `args` as the list of arguments.
-
-
-For instance, these two calls are almost the same:
+Also we need to pass not just `x`, but all arguments in `func.call`. Let's recall that in a `function()` we can get a pseudo-array of its arguments as `arguments`, so `func.call(this, x)` should be replaced with `func.call(this, ...arguments)`.
-```js
-func(1, 2, 3);
-func.apply(context, [1, 2, 3])
-```
-
-Both run `func` giving it arguments `1,2,3`. But `apply` also sets `this=context`.
-
-For instance, here `say` is called with `this=user` and `messageData` as a list of arguments:
-
-```js run
-function say(time, phrase) {
- alert(`[${time}] ${this.name}: ${phrase}`);
-}
-
-let user = { name: "John" };
-
-let messageData = ['10:00', 'Hello']; // become time and phrase
-
-*!*
-// user becomes this, messageData is passed as a list of arguments (time, phrase)
-say.apply(user, messageData); // [10:00] John: Hello (this=user)
-*/!*
-```
-
-The only syntax difference between `call` and `apply` is that `call` expects a list of arguments, while `apply` takes an array-like object with them.
-
-We already know the spread operator `...` from the chapter that can pass an array (or any iterable) as a list of arguments. So if we use it with `call`, we can achieve almost the same as `apply`.
-
-These two calls are almost equivalent:
-
-```js
-let args = [1, 2, 3];
-
-*!*
-func.call(context, ...args); // pass an array as list with spread operator
-func.apply(context, args); // is same as using apply
-*/!*
-```
-
-If we look more closely, there's a minor difference between such uses of `call` and `apply`.
-
-- The spread operator `...` allows to pass *iterable* `args` as the list to `call`.
-- The `apply` accepts only *array-like* `args`.
-
-So, these calls complement each other. Where we expect an iterable, `call` works, where we expect an array-like, `apply` works.
-
-And if `args` is both iterable and array-like, like a real array, then we technically could use any of them, but `apply` will probably be faster, because it's a single operation. Most JavaScript engines internally optimize is better than a pair `call + spread`.
-
-One of the most important uses of `apply` is passing the call to another function, like this:
-
-```js
-let wrapper = function() {
- return anotherFunction.apply(this, arguments);
-};
-```
-
-That's called *call forwarding*. The `wrapper` passes everything it gets: the context `this` and arguments to `anotherFunction` and returns back its result.
-
-When an external code calls such `wrapper`, it is undistinguishable from the call of the original function.
-
-Now let's bake it all into the more powerful `cachingDecorator`:
+Here's a more powerful `cachingDecorator`:
```js run
let worker = {
@@ -342,7 +259,7 @@ function cachingDecorator(func, hash) {
}
*!*
- let result = func.apply(this, arguments); // (**)
+ let result = func.call(this, ...arguments); // (**)
*/!*
cache.set(key, result);
@@ -360,13 +277,54 @@ alert( worker.slow(3, 5) ); // works
alert( "Again " + worker.slow(3, 5) ); // same (cached)
```
-Now the wrapper operates with any number of arguments.
+Now it works with any number of arguments (though the hash function would also need to be adjusted to allow any number of arguments. An interesting way to handle this will be covered below).
There are two changes:
- In the line `(*)` it calls `hash` to create a single key from `arguments`. Here we use a simple "joining" function that turns arguments `(3, 5)` into the key `"3,5"`. More complex cases may require other hashing functions.
-- Then `(**)` uses `func.apply` to pass both the context and all arguments the wrapper got (no matter how many) to the original function.
+- Then `(**)` uses `func.call(this, ...arguments)` to pass both the context and all arguments the wrapper got (not just the first one) to the original function.
+
+## func.apply
+
+Instead of `func.call(this, ...arguments)` we could use `func.apply(this, arguments)`.
+
+The syntax of built-in method [func.apply](mdn:js/Function/apply) is:
+
+```js
+func.apply(context, args)
+```
+
+It runs the `func` setting `this=context` and using an array-like object `args` as the list of arguments.
+
+The only syntax difference between `call` and `apply` is that `call` expects a list of arguments, while `apply` takes an array-like object with them.
+
+So these two calls are almost equivalent:
+
+```js
+func.call(context, ...args);
+func.apply(context, args);
+```
+
+They perform the same call of `func` with given context and arguments.
+
+There's only a subtle difference regarding `args`:
+
+- The spread syntax `...` allows to pass *iterable* `args` as the list to `call`.
+- The `apply` accepts only *array-like* `args`.
+...And for objects that are both iterable and array-like, such as a real array, we can use any of them, but `apply` will probably be faster, because most JavaScript engines internally optimize it better.
+
+Passing all arguments along with the context to another function is called *call forwarding*.
+
+That's the simplest form of it:
+
+```js
+let wrapper = function() {
+ return func.apply(this, arguments);
+};
+```
+
+When an external code calls such `wrapper`, it is indistinguishable from the call of the original function `func`.
## Borrowing a method [#method-borrowing]
@@ -388,7 +346,7 @@ function hash(args) {
}
```
-...Unfortunately, that won't work. Because we are calling `hash(arguments)` and `arguments` object is both iterable and array-like, but not a real array.
+...Unfortunately, that won't work. Because we are calling `hash(arguments)`, and `arguments` object is both iterable and array-like, but not a real array.
So calling `join` on it would fail, as we can see below:
@@ -416,7 +374,7 @@ hash(1, 2);
The trick is called *method borrowing*.
-We take (borrow) a join method from a regular array `[].join`. And use `[].join.call` to run it in the context of `arguments`.
+We take (borrow) a join method from a regular array (`[].join`) and use `[].join.call` to run it in the context of `arguments`.
Why does it work?
@@ -434,12 +392,20 @@ Taken from the specification almost "as-is":
So, technically it takes `this` and joins `this[0]`, `this[1]` ...etc together. It's intentionally written in a way that allows any array-like `this` (not a coincidence, many methods follow this practice). That's why it also works with `this=arguments`.
+## Decorators and function properties
+
+It is generally safe to replace a function or a method with a decorated one, except for one little thing. If the original function had properties on it, like `func.calledCount` or whatever, then the decorated one will not provide them. Because that is a wrapper. So one needs to be careful if one uses them.
+
+E.g. in the example above if `slow` function had any properties on it, then `cachingDecorator(slow)` is a wrapper without them.
+
+Some decorators may provide their own properties. E.g. a decorator may count how many times a function was invoked and how much time it took, and expose this information via wrapper properties.
+
+There exists a way to create decorators that keep access to function properties, but this requires using a special `Proxy` object to wrap a function. We'll discuss it later in the article .
+
## Summary
*Decorator* is a wrapper around a function that alters its behavior. The main job is still carried out by the function.
-It is generally safe to replace a function or a method with a decorated one, except for one little thing. If the original function had properties on it, like `func.calledCount` or whatever, then the decorated one will not provide them. Because that is a wrapper. So one need to be careful if one uses them. Some decorators provide their own properties.
-
Decorators can be seen as "features" or "aspects" that can be added to a function. We can add one or add many. And all this without changing its code!
To implement `cachingDecorator`, we studied methods:
@@ -452,10 +418,9 @@ The generic *call forwarding* is usually done with `apply`:
```js
let wrapper = function() {
return original.apply(this, arguments);
-}
+};
```
-We also saw an example of *method borrowing* when we take a method from an object and `call` it in the context of another object. It is quite common to take array methods and apply them to arguments. The alternative is to use rest parameters object that is a real array.
-
+We also saw an example of *method borrowing* when we take a method from an object and `call` it in the context of another object. It is quite common to take array methods and apply them to `arguments`. The alternative is to use rest parameters object that is a real array.
There are many decorators there in the wild. Check how well you got them by solving the tasks of this chapter.
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/decorator-makecaching-wrapper.png b/1-js/06-advanced-functions/09-call-apply-decorators/decorator-makecaching-wrapper.png
deleted file mode 100644
index 171e27910d..0000000000
Binary files a/1-js/06-advanced-functions/09-call-apply-decorators/decorator-makecaching-wrapper.png and /dev/null differ
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/decorator-makecaching-wrapper.svg b/1-js/06-advanced-functions/09-call-apply-decorators/decorator-makecaching-wrapper.svg
new file mode 100644
index 0000000000..9b63cb982b
--- /dev/null
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/decorator-makecaching-wrapper.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/decorator-makecaching-wrapper@2x.png b/1-js/06-advanced-functions/09-call-apply-decorators/decorator-makecaching-wrapper@2x.png
deleted file mode 100644
index 8d3b5434c2..0000000000
Binary files a/1-js/06-advanced-functions/09-call-apply-decorators/decorator-makecaching-wrapper@2x.png and /dev/null differ
diff --git a/1-js/06-advanced-functions/10-bind/4-function-property-after-bind/task.md b/1-js/06-advanced-functions/10-bind/4-function-property-after-bind/task.md
index 8cd18ec56c..d6cfb44bf8 100644
--- a/1-js/06-advanced-functions/10-bind/4-function-property-after-bind/task.md
+++ b/1-js/06-advanced-functions/10-bind/4-function-property-after-bind/task.md
@@ -4,7 +4,7 @@ importance: 5
# Function property after bind
-There's a value in the property of a function. Will it change after `bind`? Why, elaborate?
+There's a value in the property of a function. Will it change after `bind`? Why, or why not?
```js run
function sayHi() {
diff --git a/1-js/06-advanced-functions/10-bind/5-question-use-bind/solution.md b/1-js/06-advanced-functions/10-bind/5-question-use-bind/solution.md
index 0cb673b12b..4a381c0b40 100644
--- a/1-js/06-advanced-functions/10-bind/5-question-use-bind/solution.md
+++ b/1-js/06-advanced-functions/10-bind/5-question-use-bind/solution.md
@@ -1,5 +1,5 @@
-The error occurs because `ask` gets functions `loginOk/loginFail` without the object.
+The error occurs because `askPassword` gets functions `loginOk/loginFail` without the object.
When it calls them, they naturally assume `this=undefined`.
@@ -38,6 +38,6 @@ An alternative solution could be:
askPassword(() => user.loginOk(), () => user.loginFail());
```
-Usually that also works, but may fail in more complex situations where `user` has a chance of being overwritten between the moments of asking and running `() => user.loginOk()`.
-
+Usually that also works and looks good.
+It's a bit less reliable though in more complex situations where `user` variable might change *after* `askPassword` is called, but *before* the visitor answers and calls `() => user.loginOk()`.
diff --git a/1-js/06-advanced-functions/10-bind/5-question-use-bind/task.md b/1-js/06-advanced-functions/10-bind/5-question-use-bind/task.md
index eb19e6644d..fe6a9b4eb9 100644
--- a/1-js/06-advanced-functions/10-bind/5-question-use-bind/task.md
+++ b/1-js/06-advanced-functions/10-bind/5-question-use-bind/task.md
@@ -2,7 +2,7 @@ importance: 5
---
-# Ask losing this
+# Fix a function that loses "this"
The call to `askPassword()` in the code below should check the password and then call `user.loginOk/loginFail` depending on the answer.
@@ -34,5 +34,3 @@ let user = {
askPassword(user.loginOk, user.loginFail);
*/!*
```
-
-
diff --git a/1-js/06-advanced-functions/11-currying-partials/1-ask-currying/solution.md b/1-js/06-advanced-functions/10-bind/6-ask-partial/solution.md
similarity index 100%
rename from 1-js/06-advanced-functions/11-currying-partials/1-ask-currying/solution.md
rename to 1-js/06-advanced-functions/10-bind/6-ask-partial/solution.md
diff --git a/1-js/06-advanced-functions/10-bind/6-ask-partial/task.md b/1-js/06-advanced-functions/10-bind/6-ask-partial/task.md
new file mode 100644
index 0000000000..c90851c2bd
--- /dev/null
+++ b/1-js/06-advanced-functions/10-bind/6-ask-partial/task.md
@@ -0,0 +1,34 @@
+importance: 5
+
+---
+
+# Partial application for login
+
+The task is a little more complex variant of .
+
+The `user` object was modified. Now instead of two functions `loginOk/loginFail`, it has a single function `user.login(true/false)`.
+
+What should we pass `askPassword` in the code below, so that it calls `user.login(true)` as `ok` and `user.login(false)` as `fail`?
+
+```js
+function askPassword(ok, fail) {
+ let password = prompt("Password?", '');
+ if (password == "rockstar") ok();
+ else fail();
+}
+
+let user = {
+ name: 'John',
+
+ login(result) {
+ alert( this.name + (result ? ' logged in' : ' failed to log in') );
+ }
+};
+
+*!*
+askPassword(?, ?); // ?
+*/!*
+```
+
+Your changes should only modify the highlighted fragment.
+
diff --git a/1-js/06-advanced-functions/10-bind/article.md b/1-js/06-advanced-functions/10-bind/article.md
index 87637929fd..7a6e47b90a 100644
--- a/1-js/06-advanced-functions/10-bind/article.md
+++ b/1-js/06-advanced-functions/10-bind/article.md
@@ -5,15 +5,13 @@ libs:
# Function binding
-When using `setTimeout` with object methods or passing object methods along, there's a known problem: "losing `this`".
+When passing object methods as callbacks, for instance to `setTimeout`, there's a known problem: "losing `this`".
-Suddenly, `this` just stops working right. The situation is typical for novice developers, but happens with experienced ones as well.
-
-[cut]
+In this chapter we'll see the ways to fix it.
## Losing "this"
-We already know that in JavaScript it's easy to lose `this`. Once a method is passed somewhere separately from the object -- `this` is lost.
+We've already seen examples of losing `this`. Once a method is passed somewhere separately from the object -- `this` is lost.
Here's how it may happen with `setTimeout`:
@@ -39,13 +37,13 @@ let f = user.sayHi;
setTimeout(f, 1000); // lost user context
```
-The method `setTimeout` in-browser is a little special: it sets `this=window` for the function call (for Node.JS, `this` becomes the timer object, but doesn't really matter here). So for `this.firstName` it tries to get `window.firstName`, which does not exist. In other similar cases as we'll see, usually `this` just becomes `undefined`.
+The method `setTimeout` in-browser is a little special: it sets `this=window` for the function call (for Node.js, `this` becomes the timer object, but doesn't really matter here). So for `this.firstName` it tries to get `window.firstName`, which does not exist. In other similar cases, usually `this` just becomes `undefined`.
The task is quite typical -- we want to pass an object method somewhere else (here -- to the scheduler) where it will be called. How to make sure that it will be called in the right context?
## Solution 1: a wrapper
-The simplest solution is to use an wrapping function:
+The simplest solution is to use a wrapping function:
```js run
let user = {
@@ -72,7 +70,7 @@ setTimeout(() => user.sayHi(), 1000); // Hello, John!
Looks fine, but a slight vulnerability appears in our code structure.
-What if before `setTimeout` triggers (there's one second delay!) `user` changes value? Then, suddenly, the it will call the wrong object!
+What if before `setTimeout` triggers (there's one second delay!) `user` changes value? Then, suddenly, it will call the wrong object!
```js run
@@ -85,10 +83,12 @@ let user = {
setTimeout(() => user.sayHi(), 1000);
-// ...within 1 second
-user = { sayHi() { alert("Another user in setTimeout!"); } };
+// ...the value of user changes within 1 second
+user = {
+ sayHi() { alert("Another user in setTimeout!"); }
+};
-// Another user in setTimeout?!?
+// Another user in setTimeout!
```
The next solution guarantees that such thing won't happen.
@@ -100,9 +100,9 @@ Functions provide a built-in method [bind](mdn:js/Function/bind) that allows to
The basic syntax is:
```js
-// more complex syntax will be little later
+// more complex syntax will come a little later
let boundFunc = func.bind(context);
-````
+```
The result of `func.bind(context)` is a special function-like "exotic object", that is callable as function and transparently passes the call to `func` setting `this=context`.
@@ -125,7 +125,7 @@ funcUser(); // John
*/!*
```
-Here `func.bind(user)` as a "bound variant" of `func`, with fixed `this=user`.
+Here `func.bind(user)` is a "bound variant" of `func`, with fixed `this=user`.
All arguments are passed to the original `func` "as is", for instance:
@@ -161,9 +161,16 @@ let user = {
let sayHi = user.sayHi.bind(user); // (*)
*/!*
+// can run it without an object
sayHi(); // Hello, John!
setTimeout(sayHi, 1000); // Hello, John!
+
+// even if the value of user changes within 1 second
+// sayHi uses the pre-bound value which is reference to the old user object
+user = {
+ sayHi() { alert("Another user in setTimeout!"); }
+};
```
In the line `(*)` we take the method `user.sayHi` and bind it to `user`. The `sayHi` is a "bound" function, that can be called alone or passed to `setTimeout` -- doesn't matter, the context will be right.
@@ -180,8 +187,8 @@ let user = {
let say = user.say.bind(user);
-say("Hello"); // Hello, John ("Hello" argument is passed to say)
-say("Bye"); // Bye, John ("Bye" is passed to say)
+say("Hello"); // Hello, John! ("Hello" argument is passed to say)
+say("Bye"); // Bye, John! ("Bye" is passed to say)
```
````smart header="Convenience method: `bindAll`"
@@ -195,11 +202,127 @@ for (let key in user) {
}
```
-JavaScript libraries also provide functions for convenient mass binding , e.g. [_.bindAll(obj)](http://lodash.com/docs#bindAll) in lodash.
+JavaScript libraries also provide functions for convenient mass binding , e.g. [_.bindAll(object, methodNames)](https://lodash.com/docs#bindAll) in lodash.
````
+## Partial functions
+
+Until now we have only been talking about binding `this`. Let's take it a step further.
+
+We can bind not only `this`, but also arguments. That's rarely done, but sometimes can be handy.
+
+The full syntax of `bind`:
+
+```js
+let bound = func.bind(context, [arg1], [arg2], ...);
+```
+
+It allows to bind context as `this` and starting arguments of the function.
+
+For instance, we have a multiplication function `mul(a, b)`:
+
+```js
+function mul(a, b) {
+ return a * b;
+}
+```
+
+Let's use `bind` to create a function `double` on its base:
+
+```js run
+function mul(a, b) {
+ return a * b;
+}
+
+*!*
+let double = mul.bind(null, 2);
+*/!*
+
+alert( double(3) ); // = mul(2, 3) = 6
+alert( double(4) ); // = mul(2, 4) = 8
+alert( double(5) ); // = mul(2, 5) = 10
+```
+
+The call to `mul.bind(null, 2)` creates a new function `double` that passes calls to `mul`, fixing `null` as the context and `2` as the first argument. Further arguments are passed "as is".
+
+That's called [partial function application](https://en.wikipedia.org/wiki/Partial_application) -- we create a new function by fixing some parameters of the existing one.
+
+Please note that we actually don't use `this` here. But `bind` requires it, so we must put in something like `null`.
+
+The function `triple` in the code below triples the value:
+
+```js run
+function mul(a, b) {
+ return a * b;
+}
+
+*!*
+let triple = mul.bind(null, 3);
+*/!*
+
+alert( triple(3) ); // = mul(3, 3) = 9
+alert( triple(4) ); // = mul(3, 4) = 12
+alert( triple(5) ); // = mul(3, 5) = 15
+```
+
+Why do we usually make a partial function?
+
+The benefit is that we can create an independent function with a readable name (`double`, `triple`). We can use it and not provide the first argument every time as it's fixed with `bind`.
+
+In other cases, partial application is useful when we have a very generic function and want a less universal variant of it for convenience.
+
+For instance, we have a function `send(from, to, text)`. Then, inside a `user` object we may want to use a partial variant of it: `sendTo(to, text)` that sends from the current user.
+
+## Going partial without context
+
+What if we'd like to fix some arguments, but not the context `this`? For example, for an object method.
+
+The native `bind` does not allow that. We can't just omit the context and jump to arguments.
+
+Fortunately, a function `partial` for binding only arguments can be easily implemented.
+
+Like this:
+
+```js run
+*!*
+function partial(func, ...argsBound) {
+ return function(...args) { // (*)
+ return func.call(this, ...argsBound, ...args);
+ }
+}
+*/!*
+
+// Usage:
+let user = {
+ firstName: "John",
+ say(time, phrase) {
+ alert(`[${time}] ${this.firstName}: ${phrase}!`);
+ }
+};
+
+// add a partial method with fixed time
+user.sayNow = partial(user.say, new Date().getHours() + ':' + new Date().getMinutes());
+
+user.sayNow("Hello");
+// Something like:
+// [10:00] John: Hello!
+```
+
+The result of `partial(func[, arg1, arg2...])` call is a wrapper `(*)` that calls `func` with:
+- Same `this` as it gets (for `user.sayNow` call it's `user`)
+- Then gives it `...argsBound` -- arguments from the `partial` call (`"10:00"`)
+- Then gives it `...args` -- arguments given to the wrapper (`"Hello"`)
+
+So easy to do it with the spread syntax, right?
+
+Also there's a ready [_.partial](https://lodash.com/docs#partial) implementation from lodash library.
+
## Summary
Method `func.bind(context, ...args)` returns a "bound variant" of function `func` that fixes the context `this` and first arguments if given.
-Usually we apply `bind` to fix `this` in an object method, so that we can pass it somewhere. For example, to `setTimeout`. There are more reasons to `bind` in the modern development, we'll meet them later.
+Usually we apply `bind` to fix `this` for an object method, so that we can pass it somewhere. For example, to `setTimeout`.
+
+When we fix some arguments of an existing function, the resulting (less universal) function is called *partially applied* or *partial*.
+
+Partials are convenient when we don't want to repeat the same argument over and over again. Like if we have a `send(from, to)` function, and `from` should always be the same for our task, we can get a partial and go on with it.
diff --git a/1-js/06-advanced-functions/11-currying-partials/1-ask-currying/task.md b/1-js/06-advanced-functions/11-currying-partials/1-ask-currying/task.md
deleted file mode 100644
index 915d8aee5d..0000000000
--- a/1-js/06-advanced-functions/11-currying-partials/1-ask-currying/task.md
+++ /dev/null
@@ -1,34 +0,0 @@
-importance: 5
-
----
-
-# Partial application for login
-
-The task is a little more complex variant of .
-
-The `user` object was modified. Now instead of two functions `loginOk/loginFail`, it has a single function `user.login(true/false)`.
-
-What to pass `askPassword` in the code below, so that it calls `user.login(true)` as `ok` and `user.login(fail)` as `fail`?
-
-```js
-function askPassword(ok, fail) {
- let password = prompt("Password?", '');
- if (password == "rockstar") ok();
- else fail();
-}
-
-let user = {
- name: 'John',
-
- login(result) {
- alert( this.name + (result ? ' logged in' : ' failed to log in') );
- }
-};
-
-*!*
-askPassword(?, ?); // ?
-*/!*
-```
-
-Your changes should only modify the highlighted fragment.
-
diff --git a/1-js/06-advanced-functions/11-currying-partials/article.md b/1-js/06-advanced-functions/11-currying-partials/article.md
deleted file mode 100644
index 6e7b78e85b..0000000000
--- a/1-js/06-advanced-functions/11-currying-partials/article.md
+++ /dev/null
@@ -1,298 +0,0 @@
-libs:
- - lodash
-
----
-
-# Currying and partials
-
-Till now we were only talking about binding `this`. Now let's make a step further.
-
-We can bind not only `this`, but also arguments. That's rarely done, but sometimes can be handy.
-
-[cut]
-
-The full syntax of `bind`:
-
-```js
-let bound = func.bind(context, arg1, arg2, ...);
-```
-
-It allows to bind context as `this` and starting arguments of the function.
-
-For instance, we have a multiplication function `mul(a, b)`:
-
-```js
-function mul(a, b) {
- return a * b;
-}
-```
-
-Let's use `bind` to create a function `double` on its base:
-
-```js run
-*!*
-let double = mul.bind(null, 2);
-*/!*
-
-alert( double(3) ); // = mul(2, 3) = 6
-alert( double(4) ); // = mul(2, 4) = 8
-alert( double(5) ); // = mul(2, 5) = 10
-```
-
-The call to `mul.bind(null, 2)` creates a new function `double` that passes calls to `mul`, fixing `null` as the context and `2` as the first argument. Further arguments are passed "as is".
-
-That's called [partial function application](https://en.wikipedia.org/wiki/Partial_application) -- we create a new function by fixing some parameters of the existing one.
-
-Please note that here we actually don't use `this` here. But `bind` requires it, so we must put in something like `null`.
-
-The function `triple` in the code below triples the value:
-
-```js run
-*!*
-let triple = mul.bind(null, 3);
-*/!*
-
-alert( triple(3) ); // = mul(3, 3) = 9
-alert( triple(4) ); // = mul(3, 4) = 12
-alert( triple(5) ); // = mul(3, 5) = 15
-```
-
-Why do we usually make a partial function?
-
-Here our benefit is that we created an independent function with a readable name (`double`, `triple`). We can use it and don't write the first argument of every time, cause it's fixed with `bind`.
-
-In other cases, partial application is useful when we have a very generic function, and want a less universal variant of it for convenience.
-
-For instance, we have a function `send(from, to, text)`. Then, inside a `user` object we may want to use a partial variant of it: `sendTo(to, text)` that sends from the current user.
-
-## Going partial without context
-
-What if we'd like to fix some arguments, but not bind `this`?
-
-The native `bind` does not allow that. We can't just omit the context and jump to arguments.
-
-Fortunately, a `partial` function for binding only arguments can be easily implemented.
-
-Like this:
-
-```js run
-*!*
-function partial(func, ...argsBound) {
- return function(...args) { // (*)
- return func.call(this, ...argsBound, ...args);
- }
-}
-*/!*
-
-// Usage:
-let user = {
- firstName: "John",
- say(time, phrase) {
- alert(`[${time}] ${this.firstName}: ${phrase}!`);
- }
-};
-
-// add a partial method that says something now by fixing the first argument
-user.sayNow = partial(user.say, new Date().getHours() + ':' + new Date().getMinutes());
-
-user.sayNow("Hello");
-// Something like:
-// [10:00] Hello, John!
-```
-
-The result of `partial(func[, arg1, arg2...])` call is a wrapper `(*)` that calls `func` with:
-- Same `this` as it gets (for `user.sayNow` call it's `user`)
-- Then gives it `...argsBound` -- arguments from the `partial` call (`"10:00"`)
-- Then gives it `...args` -- arguments given to the wrapper (`"Hello"`)
-
-So easy to do it with the spread operator, right?
-
-Also there's a ready [_.partial](https://lodash.com/docs#partial) implementation from lodash library.
-
-## Currying
-
-Sometimes people mix up partial function application mentioned above with another thing named "currying". That's another interesting technique of working with functions that we just have to mention here.
-
-[Currying](https://en.wikipedia.org/wiki/Currying) is translating a function from callable as `f(a, b, c)` into callable as `f(a)(b)(c)`.
-
-Let's make `curry` function that performs currying for binary functions. In other words, it translates `f(a, b)` into `f(a)(b)`:
-
-```js run
-*!*
-function curry(func) {
- return function(a) {
- return function(b) {
- return func(a, b);
- };
- };
-}
-*/!*
-
-// usage
-function sum(a, b) {
- return a + b;
-}
-
-let carriedSum = curry(sum);
-
-alert( carriedSum(1)(2) ); // 3
-```
-
-As you can see, the implementation is a series of wrappers.
-
-- The result of `curry(func)` is a wrapper `function(a)`.
-- When it is called like `sum(1)`, the argument is saved in the Lexical Environment, and a new wrapper is returned `function(b)`.
-- Then `sum(1)(2)` finally calls `function(b)` providing `2`, and it passes the call to the original multi-argument `sum`.
-
-More advanced implementations of currying like [_.curry](https://lodash.com/docs#curry) from lodash library do something more sophisticated. They return a wrapper that allows a function to be called normally when all arguments are supplied *or* returns a partial otherwise.
-
-```js
-function curry(f) {
- return function(..args) {
- // if args.length == f.length (as many arguments as f has),
- // then pass the call to f
- // otherwise return a partial function that fixes args as first arguments
- };
-}
-```
-
-## Currying? What for?
-
-Advanced currying allows both to keep the function callable normally and to get partials easily. To understand the benefits we definitely need a worthy real-life example.
-
-For instance, we have the logging function `log(date, importance, message)` that formats and outputs the information. In real projects such functions also have many other useful features like: sending it over the network or filtering:
-
-```js
-function log(date, importance, message) {
- alert(`[${date.getHours()}:${date.getMinutes()}] [${importance}] ${message}`);
-}
-```
-
-Let's curry it!
-
-```js
-log = _.curry(log);
-```
-
-After that `log` still works the normal way:
-
-```js
-log(new Date(), "DEBUG", "some debug");
-```
-
-...But also can be called in the curried form:
-
-```js
-log(new Date())("DEBUG")("some debug"); // log(a)(b)(c)
-```
-
-Let's get a convenience function for today's logs:
-
-```js
-// todayLog will be the partial of log with fixed first argument
-let todayLog = log(new Date());
-
-// use it
-todayLog("INFO", "message"); // [HH:mm] INFO message
-```
-
-And now a convenience function for today's debug messages:
-
-```js
-let todayDebug = todayLog("DEBUG");
-
-todayDebug("message"); // [HH:mm] DEBUG message
-```
-
-So:
-1. We didn't lose anything after currying: `log` is still callable normally.
-2. We were able to generate partial functions that are convenient in many cases.
-
-## Advanced curry implementation
-
-In case you're interested, here's the "advanced" curry implementation that we could use above.
-
-```js run
-function curry(func) {
-
- return function curried(...args) {
- if (args.length >= func.length) {
- return func.apply(this, args);
- } else {
- return function(...args2) {
- return curried.apply(this, args.concat(args2));
- }
- }
- };
-
-}
-
-function sum(a, b, c) {
- return a + b + c;
-}
-
-let curriedSum = curry(sum);
-
-// still callable normally
-alert( curriedSum(1, 2, 3) ); // 6
-
-// get the partial with curried(1) and call it with 2 other arguments
-alert( curriedSum(1)(2,3) ); // 6
-
-// full curried form
-alert( curriedSum(1)(2)(3) ); // 6
-```
-
-The new `curry` may look complicated, but it's actually pretty easy to understand.
-
-The result of `curry(func)` is the wrapper `curried` that looks like this:
-
-```js
-// func is the function to transform
-function curried(...args) {
- if (args.length >= func.length) { // (1)
- return func.apply(this, args);
- } else {
- return function pass(...args2) { // (2)
- return curried.apply(this, args.concat(args2));
- }
- }
-};
-```
-
-When we run it, there are two branches:
-
-1. Call now: if passed `args` count is the same as the original function has in its definition (`func.length`) or longer, then just pass the call to it.
-2. Get a partial: otherwise, `func` is not called yet. Instead, another wrapper `pass` is returned, that will re-apply `curried` providing previous arguments together with the new ones. Then on a new call, again, we'll get either a new partial (if not enough arguments) or, finally, the result.
-
-For instance, let's see what happens in the case of `sum(a, b, c)`. Three arguments, so `sum.length = 3`.
-
-For the call `curried(1)(2)(3)`:
-
-1. The first call `curried(1)` remembers `1` in its Lexical Environment, and returns a wrapper `pass`.
-2. The wrapper `pass` is called with `(2)`: it takes previous args (`1`), concatenates them with what it got `(2)` and calls `curried(1, 2)` with them together.
-
- As the argument count is still less than 3, `curry` returns `pass`.
-3. The wrapper `pass` is called again with `(3)`, for the next call `pass(3)` takes previous args (`1`, `2`) and adds `3` to them, making the call `curried(1, 2, 3)` -- there are `3` arguments at last, they are given to the original function.
-
-If that's still not obvious, just trace the calls sequence in your mind or on the paper.
-
-```smart header="Fixed-length functions only"
-The currying requires the function to have a known fixed number of arguments.
-```
-
-```smart header="A little more than currying"
-By definition, currying should convert `sum(a, b, c)` into `sum(a)(b)(c)`.
-
-But most implementations of currying in JavaScript are advanced, as described: they also keep the function callable in the multi-argument variant.
-```
-
-## Summary
-
-- When we fix some arguments of an existing function, the resulting (less universal) function is called *a partial*. We can use `bind` to get a partial, but there are other ways also.
-
- Partials are convenient when we don't want to repeat the same argument over and over again. Like if we have a `send(from, to)` function, and `from` should always be the same for our task, we can get a partial and go on with it.
-
-- *Currying* is a transform that makes `f(a,b,c)` callable as `f(a)(b)(c)`. JavaScript implementations usually both keep the function callable normally and return the partial if arguments count is not enough.
-
- Currying is great when we want easy partials. As we've seen in the logging example: the universal function `log(date, importance, message)` after currying gives us partials when called with one argument like `log(date)` or two arguments `log(date, importance)`.
diff --git a/1-js/06-advanced-functions/12-arrow-functions/article.md b/1-js/06-advanced-functions/12-arrow-functions/article.md
index dcae22a4e6..8730277ad7 100644
--- a/1-js/06-advanced-functions/12-arrow-functions/article.md
+++ b/1-js/06-advanced-functions/12-arrow-functions/article.md
@@ -2,11 +2,9 @@
Let's revisit arrow functions.
-[cut]
+Arrow functions are not just a "shorthand" for writing small stuff. They have some very specific and useful features.
-Arrow functions are not just a "shorthand" for writing small stuff.
-
-JavaScript is full of situations where we need to write a small function, that's executed somewhere else.
+JavaScript is full of situations where we need to write a small function that's executed somewhere else.
For instance:
@@ -16,7 +14,7 @@ For instance:
It's in the very spirit of JavaScript to create a function and pass it somewhere.
-And in such functions we usually don't want to leave the current context.
+And in such functions we usually don't want to leave the current context. That's where arrow functions come in handy.
## Arrow functions have no "this"
@@ -54,7 +52,7 @@ let group = {
*!*
this.students.forEach(function(student) {
// Error: Cannot read property 'title' of undefined
- alert(this.title + ': ' + student)
+ alert(this.title + ': ' + student);
});
*/!*
}
@@ -89,7 +87,7 @@ For instance, `defer(f, ms)` gets a function and returns a wrapper around it tha
```js run
function defer(f, ms) {
return function() {
- setTimeout(() => f.apply(this, arguments), ms)
+ setTimeout(() => f.apply(this, arguments), ms);
};
}
@@ -120,9 +118,9 @@ Here we had to create additional variables `args` and `ctx` so that the function
Arrow functions:
-- Do not have `this`.
-- Do not have `arguments`.
-- Can't be called with `new`.
-- (They also don't have `super`, but we didn't study it. Will be in the chapter ).
+- Do not have `this`
+- Do not have `arguments`
+- Can't be called with `new`
+- They also don't have `super`, but we didn't study it yet. We will on the chapter
-That's because they are meant for short pieces of code that does not have their own "context", but rather works in the current one. And they really shine in that use case.
+That's because they are meant for short pieces of code that do not have their own "context", but rather work in the current one. And they really shine in that use case.
diff --git a/1-js/07-object-oriented-programming/01-property-descriptors/article.md b/1-js/07-object-oriented-programming/01-property-descriptors/article.md
deleted file mode 100644
index 92d83365a2..0000000000
--- a/1-js/07-object-oriented-programming/01-property-descriptors/article.md
+++ /dev/null
@@ -1,311 +0,0 @@
-
-# Property flags and descriptors
-
-As we know, objects can store properties.
-
-Till now, a property was a simple "key-value" pair to us. But an object property is actually more complex and tunable thing.
-
-[cut]
-
-## Property flags
-
-Object properties, besides a **`value`**, have three special attributes (so-called "flags"):
-
-- **`writable`** -- if `true`, can be changed, otherwise it's read-only.
-- **`enumerable`** -- if `true`, then listed in loops, otherwise not listed.
-- **`configurable`** -- if `true`, the property can be deleted and these attributes can be modified, otherwise not.
-
-We didn't see them yet, because generally they do not show up. When we create a property "the usual way", all of them are `true`. But we also can change them any time.
-
-First, let's see how to get those flags.
-
-The method [Object.getOwnPropertyDescriptor](mdn:js/Object/getOwnPropertyDescriptor) allows to query the *full* information about a property.
-
-The syntax is:
-```js
-let descriptor = Object.getOwnPropertyDescriptor(obj, propertyName);
-```
-
-`obj`
-: The object to get information from.
-
-`propertyName`
-: The name of the property.
-
-The returned value is a so-called "property descriptor" object: it contains the value and all the flags.
-
-For instance:
-
-```js run
-let user = {
- name: "John"
-};
-
-let descriptor = Object.getOwnPropertyDescriptor(user, 'name');
-
-alert( JSON.stringify(descriptor, null, 2 ) );
-/* property descriptor:
-{
- "value": "John",
- "writable": true,
- "enumerable": true,
- "configurable": true
-}
-*/
-```
-
-To change the flags, we can use [Object.defineProperty](mdn:js/Object/defineProperty).
-
-The syntax is:
-
-```js
-Object.defineProperty(obj, propertyName, descriptor)
-```
-
-`obj`, `propertyName`
-: The object and property to work on.
-
-`descriptor`
-: Property descriptor to apply.
-
-If the property exists, `defineProperty` updates its flags. Otherwise, it creates the property with the given value and flags; in that case, if a flag is not supplied, it is assumed `false`.
-
-For instance, here a property `name` is created with all falsy flags:
-
-```js run
-let user = {};
-
-*!*
-Object.defineProperty(user, "name", {
- value: "John"
-});
-*/!*
-
-let descriptor = Object.getOwnPropertyDescriptor(user, 'name');
-
-alert( JSON.stringify(descriptor, null, 2 ) );
-/*
-{
- "value": "John",
-*!*
- "writable": false,
- "enumerable": false,
- "configurable": false
-*/!*
-}
- */
-```
-
-Compare it with "normally created" `user.name` above: now all flags are falsy. If that's not what we want then we'd better set them to `true` in `descriptor`.
-
-Now let's see effects of the flags by example.
-
-## Read-only
-
-Let's make `user.name` read-only by changing `writable` flag:
-
-```js run
-let user = {
- name: "John"
-};
-
-Object.defineProperty(user, "name", {
-*!*
- writable: false
-*/!*
-});
-
-*!*
-user.name = "Pete"; // Error: Cannot assign to read only property 'name'...
-*/!*
-```
-
-Now no one can change the name of our user, unless he applies his own `defineProperty` to override ours.
-
-Here's the same operation, but for the case when a property doesn't exist:
-
-```js run
-let user = { };
-
-Object.defineProperty(user, "name", {
-*!*
- value: "Pete",
- // for new properties need to explicitly list what's true
- enumerable: true,
- configurable: true
-*/!*
-});
-
-alert(user.name); // Pete
-user.name = "Alice"; // Error
-```
-
-
-## Non-enumerable
-
-Now let's a custom `toString` to `user`.
-
-Normally, a built-in `toString` for objects is non-enumerable, it does not show up in `for..in`. But if we add `toString` of our own, then by default it shows up in `for..in`.
-
-...But if we don't like it, then we can set `enumerable:false`. Then it won't appear in `for..in` loop, just like the built-in one:
-
-```js run
-let user = {
- name: "John",
- toString() {
- return this.name;
- }
-};
-
-// By default, both our properties are listed:
-for(let key in user) alert(key); // name, toString
-
-Object.defineProperty(user, "toString", {
-*!*
- enumerable: false
-*/!*
-});
-
-*!*
-// Now toString disappears:
-*/!*
-for(let key in user) alert(key); // name
-```
-
-Non-enumerable properties are also excluded from `Object.keys`:
-
-```js
-alert(Object.keys(user)); // name
-```
-
-
-
-## Non-configurable
-
-The non-configurable flag (`configurable:false`) is usually set for built-in objects and properties.
-
-A non-configurable property can not be deleted or altered with `defineProperty`.
-
-For instance, `Math.PI` is both read-only, non-enumerable and non-configurable:
-
-```js run
-let descriptor = Object.getOwnPropertyDescriptor(Math, 'PI');
-
-alert( JSON.stringify(descriptor, null, 2 ) );
-/*
-{
- "value": 3.141592653589793,
- "writable": false,
- "enumerable": false,
- "configurable": false
-}
-*/
-```
-So, a programmer is unable to change the value of `Math.PI` or overwrite it.
-
-```js run
-Math.PI = 3; // Error
-
-// delete Math.PI won't work either
-```
-
-Making a property non-configurable is a one-way road. We cannot change it back, because `defineProperty` doesn't work on non-configurable properties.
-
-Here we are making `user.name` a "forever sealed" constant:
-
-```js run
-let user = { };
-
-Object.defineProperty(user, "name", {
- value: "John",
- writable: false,
- configurable: false
-});
-
-*!*
-// won't be able to change user.name or its flags
-// all this won't work:
-// user.name = "Pete"
-// delete user.name
-// defineProperty(user, "name", ...)
-Object.defineProperty(user, "name", {writable: true}); // Error
-*/!*
-```
-
-```smart header="Errors appear only in use strict"
-In the non-strict mode, no errors occur when writing to read-only properties and such. But the operation still won't succeed. Flag-violating actions are just silently ignored in non-strict.
-```
-
-## Object.defineProperties
-
-There's a method [Object.defineProperties(obj, descriptors)](mdn:js/Object/defineProperties) that allows to define many properties at once.
-
-The syntax is:
-
-```js
-Object.defineProperties(obj, {
- prop1: descriptor1,
- prop2: descriptor2
- // ...
-});
-```
-
-For instance:
-
-```js
-Object.defineProperties(user, {
- name: { value: "John", writable: false },
- surname: { value: "Smith", writable: false },
- // ...
-});
-```
-
-So, we can set many properties at once.
-
-## Object.getOwnPropertyDescriptors
-
-To get many descriptors at once, we can use the method [Object.getOwnPropertyDescriptors(obj)](mdn:js/Object/getOwnPropertyDescriptors).
-
-Together with `Object.defineProperties` it can be used as a "flags-aware" way of cloning an object:
-
-```js
-let clone = Object.defineProperties({}, Object.getOwnPropertyDescriptors(obj));
-```
-
-Normally when we clone an object, we use an assignment to copy properties, like this:
-
-```js
-for(let key in user) {
- clone[key] = user[key]
-}
-```
-
-...But that does not copy flags. So if we want a "better" clone then `Object.defineProperties` is preferred.
-
-## Sealing an object globally
-
-Property descriptors work at the level of individual properties.
-
-There are also methods that limit access to the *whole* object:
-
-[Object.preventExtensions(obj)](mdn:js/Object/preventExtensions)
-: Forbids to add properties to the object.
-
-[Object.seal(obj)](mdn:js/Object/seal)
-: Forbids to add/remove properties, sets for all existing properties `configurable: false`.
-
-[Object.freeze(obj)](mdn:js/Object/freeze)
-: Forbids to add/remove/change properties, sets for all existing properties `configurable: false, writable: false`.
-
-And also there are tests for them:
-
-[Object.isExtensible(obj)](mdn:js/Object/isExtensible)
-: Returns `false` if adding properties is forbidden, otherwise `true`.
-
-[Object.isSealed(obj)](mdn:js/Object/isSealed)
-: Returns `true` if adding/removing properties is forbidden, and all existing properties have `configurable: false`.
-
-[Object.isFrozen(obj)](mdn:js/Object/isFrozen)
-: Returns `true` if adding/removing/changing properties is forbidden, and all current properties are `configurable: false, writable: false`.
-
-These methods are rarely used in practice.
diff --git a/1-js/07-object-oriented-programming/02-property-accessors/article.md b/1-js/07-object-oriented-programming/02-property-accessors/article.md
deleted file mode 100644
index 616348e7d1..0000000000
--- a/1-js/07-object-oriented-programming/02-property-accessors/article.md
+++ /dev/null
@@ -1,239 +0,0 @@
-
-# Property getters and setters
-
-There are two kinds of properties.
-
-The first kind is *data properties*. We already know how to work with them. Actually, all properties that we've been using till now were data properties.
-
-The second type of properties is something new. It's *accessor properties*. They are essentially functions that work on getting and setting a value, but look like regular properties to an external code.
-
-[cut]
-
-## Getters and setters
-
-Accessor properties are represented by "getter" and "setter" methods. In an object literal they are denoted by `get` and `set`:
-
-```js
-let obj = {
- *!*get propName()*/!* {
- // getter, the code executed on getting obj.propName
- },
-
- *!*set propName(value)*/!* {
- // setter, the code executed on setting obj.propName = value
- }
-};
-```
-
-The getter works when `obj.propName` is read, the setter -- when it is assigned.
-
-For instance, we have a `user` object with `name` and `surname`:
-
-```js run
-let user = {
- name: "John",
- surname: "Smith"
-};
-```
-
-Now we want to add a "fullName" property, that should be "John Smith". Of course, we don't want to copy-paste existing information, so we can implement it as an accessor:
-
-```js run
-let user = {
- name: "John",
- surname: "Smith",
-
-*!*
- get fullName() {
- return `${this.name} ${this.surname}`;
- }
-*/!*
-};
-
-*!*
-alert(user.fullName); // John Smith
-*/!*
-```
-
-From outside, an accessor property looks like a regular one. That's the idea of accessor properties. We don't *call* `user.fullName` as a function, we *read* it normally: the getter runs behind the scenes.
-
-As of now, `fullName` has only a getter. If we attempt to assign `user.fullName=`, there will be an error.
-
-Let's fix it by adding a setter for `user.fullName`:
-
-```js run
-let user = {
- name: "John",
- surname: "Smith",
-
- get fullName() {
- return `${this.name} ${this.surname}`;
- },
-
-*!*
- set fullName(value) {
- [this.name, this.surname] = value.split(" ");
- }
-*/!*
-};
-
-// set fullName is executed with the given value.
-user.fullName = "Alice Cooper";
-
-alert(user.name); // Alice
-alert(user.surname); // Cooper
-```
-
-Now we have a "virtual" property. It is readable and writable, but in fact does not exist.
-
-```smart header="Accessor properties are only accessible with get/set"
-A property can either be a "data property" or an "accessor property", but not both.
-
-Once a property is defined with `get prop()` or `set prop()`, it's an accessor property. So there must be a getter to read it, and must be a setter if we want to assign it.
-
-Sometimes it's normal that there's only a setter or only a getter. But the property won't be readable or writable in that case.
-```
-
-
-## Accessor descriptors
-
-Descriptors for accessor properties are different -- as compared with data properties.
-
-For accessor properties, there is no `value` and `writable`, but instead there are `get` and `set` functions.
-
-So an accessor descriptor may have:
-
-- **`get`** -- a function without arguments, that works when a property is read,
-- **`set`** -- a function with one argument, that is called when the property is set,
-- **`enumerable`** -- same as for data properties,
-- **`configurable`** -- same as for data properties.
-
-For instance, to create an accessor `fullName` with `defineProperty`, we can pass a descriptor with `get` and `set`:
-
-```js run
-let user = {
- name: "John",
- surname: "Smith"
-};
-
-*!*
-Object.defineProperty(user, 'fullName', {
- get() {
- return `${this.name} ${this.surname}`;
- },
-
- set(value) {
- [this.name, this.surname] = value.split(" ");
- }
-*/!*
-});
-
-alert(user.fullName); // John Smith
-
-for(let key in user) alert(key);
-```
-
-Please note once again that a property can be either an accessor or a data property, not both.
-
-If we try to supply both `get` and `value` in the same descriptor, there will be an error:
-
-```js run
-*!*
-// Error: Invalid property descriptor.
-*/!*
-Object.defineProperty({}, 'prop', {
- get() {
- return 1
- },
-
- value: 2
-});
-```
-
-## Smarter getters/setters
-
-Getters/setters can be used as wrappers over "real" property values to gain more control over them.
-
-For instance, if we want to forbid too short names for `user`, we can store `name` in a special property `_name`. And filter assignments in the setter:
-
-```js run
-let user = {
- get name() {
- return this._name;
- },
-
- set name(value) {
- if (value.length < 4) {
- alert("Name is too short, need at least 4 characters");
- return;
- }
- this._name = value;
- }
-};
-
-user.name = "Pete";
-alert(user.name); // Pete
-
-user.name = ""; // Name is too short...
-```
-
-Technically, the external code may still access the name directly by using `user._name`. But there is a widely known agreement that properties starting with an underscore `"_"` are internal and should not be touched from outside the object.
-
-
-## Using for compatibility
-
-One of the great ideas behind getters and setters -- they allow to take control over a "normal" data property and tweak it at any moment.
-
-For instance, we started implementing user objects using data properties `name` and `age`:
-
-```js
-function User(name, age) {
- this.name = name;
- this.age = age;
-}
-
-let john = new User("John", 25);
-
-alert( john.age ); // 25
-```
-
-...But sooner or later, things may change. Instead of `age` we may decide to store `birthday`, because it's more precise and convenient:
-
-```js
-function User(name, birthday) {
- this.name = name;
- this.birthday = birthday;
-}
-
-let john = new User("John", new Date(1992, 6, 1));
-```
-
-Now what to do with the old code that still uses `age` property?
-
-We can try to find all such places and fix them, but that takes time and can be hard to do if that code is written by other people. And besides, `age` is a nice thing to have in `user`, right? In some places it's just what we want.
-
-Adding a getter for `age` mitigates the problem:
-
-```js run no-beautify
-function User(name, birthday) {
- this.name = name;
- this.birthday = birthday;
-
-*!*
- // age is calculated from the current date and birthday
- Object.defineProperty(this, "age", {
- get() {
- let todayYear = new Date().getFullYear();
- return todayYear - this.birthday.getFullYear();
- }
- });
-*/!*
-}
-
-let john = new User("John", new Date(1992, 6, 1));
-
-alert( john.birthday ); // birthday is available
-alert( john.age ); // ...as well as the age
-```
-
-Now the old code works too and we've got a nice additional property.
diff --git a/1-js/07-object-oriented-programming/03-prototype-inheritance/2-search-algorithm/task.md b/1-js/07-object-oriented-programming/03-prototype-inheritance/2-search-algorithm/task.md
deleted file mode 100644
index 70b8b28801..0000000000
--- a/1-js/07-object-oriented-programming/03-prototype-inheritance/2-search-algorithm/task.md
+++ /dev/null
@@ -1,31 +0,0 @@
-importance: 5
-
----
-
-# Searching algorithm
-
-The task has two parts.
-
-We have an object:
-
-```js
-let head = {
- glasses: 1
-};
-
-let table = {
- pen: 3
-};
-
-let bed = {
- sheet: 1,
- pillow: 2
-};
-
-let pockets = {
- money: 2000
-};
-```
-
-1. Use `__proto__` to assign prototypes in a way that any property lookup will follow the path: `pockets` -> `bed` -> `table` -> `head`. For instance, `pockets.pen` should be `3` (found in `table`), and `bed.glasses` should be `1` (found in `head`).
-2. Answer the question: is it faster to get `glasses` as `pocket.glasses` or `head.glasses`? Benchmark if needed.
diff --git a/1-js/07-object-oriented-programming/03-prototype-inheritance/3-proto-and-this/solution.md b/1-js/07-object-oriented-programming/03-prototype-inheritance/3-proto-and-this/solution.md
deleted file mode 100644
index c7d147b9c7..0000000000
--- a/1-js/07-object-oriented-programming/03-prototype-inheritance/3-proto-and-this/solution.md
+++ /dev/null
@@ -1,6 +0,0 @@
-**The answer: `rabbit`.**
-
-That's because `this` is an object before the dot, so `rabbit.eat()` modifies `rabbit`.
-
-Property lookup and execution are two different things.
-The method `rabbit.eat` is first found in the prototype, then executed with `this=rabbit`
diff --git a/1-js/07-object-oriented-programming/03-prototype-inheritance/3-proto-and-this/task.md b/1-js/07-object-oriented-programming/03-prototype-inheritance/3-proto-and-this/task.md
deleted file mode 100644
index b37499bad5..0000000000
--- a/1-js/07-object-oriented-programming/03-prototype-inheritance/3-proto-and-this/task.md
+++ /dev/null
@@ -1,23 +0,0 @@
-importance: 5
-
----
-
-# Where it writes?
-
-We have `rabbit` inheriting from `animal`.
-
-If we call `rabbit.eat()`, which object receives the `full` property: `animal` or `rabbit`?
-
-```js
-let animal = {
- eat() {
- this.full = true;
- }
-};
-
-let rabbit = {
- __proto__: animal
-};
-
-rabbit.eat();
-```
diff --git a/1-js/07-object-oriented-programming/03-prototype-inheritance/4-hamster-proto/solution.md b/1-js/07-object-oriented-programming/03-prototype-inheritance/4-hamster-proto/solution.md
deleted file mode 100644
index 8ffdb76ca6..0000000000
--- a/1-js/07-object-oriented-programming/03-prototype-inheritance/4-hamster-proto/solution.md
+++ /dev/null
@@ -1,80 +0,0 @@
-Let's look carefully at what's going on in the call `speedy.eat("apple")`.
-
-1. The method `speedy.eat` is found in the prototype (`=hamster`), then executed with `this=speedy` (the object before the dot).
-
-2. Then `this.stomach.push()` needs to find `stomach` property and call `push` on it. It looks for `stomach` in `this` (`=speedy`), but nothing found.
-
-3. Then it follows the prototype chain and finds `stomach` in `hamster`.
-
-4. Then it calls `push` on it, adding the food into *the stomach of the prototype*.
-
-So all hamsters share a single stomach!
-
-Every time the `stomach` is taken from the prototype, then `stomach.push` modifies it "at place".
-
-Please note that such thing doesn't happen in case of a simple assignment `this.stomach=`:
-
-```js run
-let hamster = {
- stomach: [],
-
- eat(food) {
-*!*
- // assign to this.stomach instead of this.stomach.push
- this.stomach = [food];
-*/!*
- }
-};
-
-let speedy = {
- __proto__: hamster
-};
-
-let lazy = {
- __proto__: hamster
-};
-
-// Speedy one found the food
-speedy.eat("apple");
-alert( speedy.stomach ); // apple
-
-// Lazy one's stomach is empty
-alert( lazy.stomach ); //
-```
-
-Now all works fine, because `this.stomach=` does not perform a lookup of `stomach`. The value is written directly into `this` object.
-
-Also we can totally evade the problem by making sure that each hamster has his own stomach:
-
-```js run
-let hamster = {
- stomach: [],
-
- eat(food) {
- this.stomach.push(food);
- }
-};
-
-let speedy = {
- __proto__: hamster,
-*!*
- stomach: []
-*/!*
-};
-
-let lazy = {
- __proto__: hamster,
-*!*
- stomach: []
-*/!*
-};
-
-// Speedy one found the food
-speedy.eat("apple");
-alert( speedy.stomach ); // apple
-
-// Lazy one's stomach is empty
-alert( lazy.stomach ); //
-```
-
-As a common solution, all properties that describe the state of a particular object, like `stomach` above, are usually written into that object. That prevents such problems.
diff --git a/1-js/07-object-oriented-programming/03-prototype-inheritance/4-hamster-proto/task.md b/1-js/07-object-oriented-programming/03-prototype-inheritance/4-hamster-proto/task.md
deleted file mode 100644
index 6f9fb279ec..0000000000
--- a/1-js/07-object-oriented-programming/03-prototype-inheritance/4-hamster-proto/task.md
+++ /dev/null
@@ -1,35 +0,0 @@
-importance: 5
-
----
-
-# Why two hamsters are full?
-
-We have two hamsters: `speedy` and `lazy` inheriting from the general `hamster` object.
-
-When we feed one of them, the other one is also full. Why? How to fix it?
-
-```js run
-let hamster = {
- stomach: [],
-
- eat(food) {
- this.stomach.push(food);
- }
-};
-
-let speedy = {
- __proto__: hamster
-};
-
-let lazy = {
- __proto__: hamster
-};
-
-// This one found the food
-speedy.eat("apple");
-alert( speedy.stomach ); // apple
-
-// This one also has it, why? fix please.
-alert( lazy.stomach ); // apple
-```
-
diff --git a/1-js/07-object-oriented-programming/03-prototype-inheritance/article.md b/1-js/07-object-oriented-programming/03-prototype-inheritance/article.md
deleted file mode 100644
index 40dff06b0d..0000000000
--- a/1-js/07-object-oriented-programming/03-prototype-inheritance/article.md
+++ /dev/null
@@ -1,252 +0,0 @@
-# Prototypal inheritance
-
-In programming, we often want to take something and extend it.
-
-For instance, we have a `user` object with its properties and methods, and want to make `admin` and `guest` as slightly modified variants of it. We'd like to reuse what we have in `user`, not copy/reimplement its methods, just build a new object on top of it.
-
-*Prototypal inheritance* is a language feature that helps in that.
-
-[cut]
-
-## [[Prototype]]
-
-In JavaScript, objects have a special hidden property `[[Prototype]]` (as named in the specification), that is either `null` or references another object. That object is called "a prototype":
-
-
-
-That `[[Prototype]]` has a "magical" meaning. When we want to read a property from `object`, and it's missing, JavaScript automatically takes it from the prototype. In programming, such thing is called "prototypal inheritance". Many cool language features and programming techniques are based on it.
-
-The property `[[Prototype]]` is internal and hidden, but there are many ways to set it.
-
-One of them is to use `__proto__`, like this:
-
-```js run
-let animal = {
- eats: true
-};
-let rabbit = {
- jumps: true
-};
-
-*!*
-rabbit.__proto__ = animal;
-*/!*
-```
-
-Please note that `__proto__` is *not the same* as `[[Prototype]]`. That's a getter/setter for it. We'll talk about other ways of setting it later, but for now `__proto__` will do just fine.
-
-If we look for a property in `rabbit`, and it's missing, JavaScript automatically takes it from `animal`.
-
-For instance:
-
-```js run
-let animal = {
- eats: true
-};
-let rabbit = {
- jumps: true
-};
-
-*!*
-rabbit.__proto__ = animal; // (*)
-*/!*
-
-// we can find both properties in rabbit now:
-*!*
-alert( rabbit.eats ); // true (**)
-*/!*
-alert( rabbit.jumps ); // true
-```
-
-Here the line `(*)` sets `animal` to be a prototype of `rabbit`.
-
-Then, when `alert` tries to read property `rabbit.eats` `(**)`, it's not in `rabbit`, so JavaScript follows the `[[Prototype]]` reference and finds it in `animal` (look from the bottom up):
-
-
-
-Here we can say that "`animal` is the prototype of `rabbit`" or "`rabbit` prototypally inherits from `animal`".
-
-So if `animal` has a lot of useful properties and methods, then they become automatically available in `rabbit`. Such properties are called "inherited".
-
-If we have a method in `animal`, it can be called on `rabbit`:
-
-```js run
-let animal = {
- eats: true,
-*!*
- walk() {
- alert("Animal walk");
- }
-*/!*
-};
-
-let rabbit = {
- jumps: true,
- __proto__: animal
-};
-
-// walk is taken from the prototype
-*!*
-rabbit.walk(); // Animal walk
-*/!*
-```
-
-The method is automatically taken from the prototype, like this:
-
-
-
-The prototype chain can be longer:
-
-
-```js run
-let animal = {
- eats: true,
- walk() {
- alert("Animal walk");
- }
-};
-
-let rabbit = {
- jumps: true,
- __proto__: animal
-};
-
-let longEar = {
- earLength: 10,
- __proto__: rabbit
-}
-
-// walk is taken from the prototype chain
-longEar.walk(); // Animal walk
-alert(longEar.jumps); // true (from rabbit)
-```
-
-
-
-There are actually only two limitations:
-
-1. The references can't go in circles. JavaScript will throw an error if we try to assign `__proto__` in a circle.
-2. The value of `__proto__` can be either an object or `null`. All other values (like primitives) are ignored.
-
-Also it may be obvious, but still: there can be only one `[[Prototype]]`. An object may not inherit from two others.
-
-## Read/write rules
-
-The prototype is only used for reading properties.
-
-For data properties (not getters/setters) write/delete operations work directly with the object.
-
-In the example below, we assign its own `walk` method to `rabbit`:
-
-```js run
-let animal = {
- eats: true,
- walk() {
- /* this method won't be used by rabbit */
- }
-};
-
-let rabbit = {
- __proto__: animal
-}
-
-*!*
-rabbit.walk = function() {
- alert("Rabbit! Bounce-bounce!");
-};
-*/!*
-
-rabbit.walk(); // Rabbit! Bounce-bounce!
-```
-
-From now on, `rabbit.walk()` call finds the method immediately in the object and executes it, without using the prototype:
-
-
-
-For getters/setters -- if we read/write a property, they are looked up in the prototype and invoked.
-
-For instance, check out `admin.fullName` property in the code below:
-
-```js run
-let user = {
- name: "John",
- surname: "Smith",
-
- set fullName(value) {
- [this.name, this.surname] = value.split(" ");
- },
-
- get fullName() {
- return `${this.name} ${this.surname}`;
- }
-};
-
-let admin = {
- __proto__: user,
- isAdmin: true
-};
-
-alert(admin.fullName); // John Smith (*)
-
-// setter triggers!
-admin.fullName = "Alice Cooper"; // (**)
-```
-
-Here in the line `(*)` the property `admin.fullName` has a getter in the prototype `user`, so it is called. And in the line `(**)` the property has a setter in the prototype, so it is called.
-
-## The value of "this"
-
-An interesting question may arise in the example above: what's the value of `this` inside `set fullName(value)`? Where the properties `this.name` and `this.surname` are written: `user` or `admin`?
-
-The answer is simple: `this` is not affected by prototypes at all.
-
-**No matter where the method is found: in an object or its prototype. In a method call, `this` is always the object before the dot.**
-
-So, the setter actually uses `admin` as `this`, not `user`.
-
-That is actually a super-important thing, because we may have a big object with many methods and inherit from it. Then we can run its methods on inherited objects and they will modify the state of these objects, not the big one.
-
-For instance, here `animal` represents a "method storage", and `rabbit` makes use of it.
-
-The call `rabbit.sleep()` sets `this.isSleeping` on the `rabbit` object:
-
-```js run
-// animal has methods
-let animal = {
- walk() {
- if (!this.isSleeping) {
- alert(`I walk`);
- }
- },
- sleep() {
- this.isSleeping = true;
- }
-};
-
-let rabbit = {
- name: "White Rabbit",
- __proto__: animal
-};
-
-// modifies rabbit.isSleeping
-rabbit.sleep();
-
-alert(rabbit.isSleeping); // true
-alert(animal.isSleeping); // undefined (no such property in the prototype)
-```
-
-The resulting picture:
-
-
-
-If we had other objects like `bird`, `snake` etc inheriting from `animal`, they would also gain access to methods of `animal`. But `this` in each method would be the corresponding object, evaluated at the call-time (before dot), not `animal`. So when we write data into `this`, it is stored into these objects.
-
-As a result, methods are shared, but the object state is not.
-
-## Summary
-
-- In JavaScript, all objects have a hidden `[[Prototype]]` property that's either another object or `null`.
-- We can use `obj.__proto__` to access it (there are other ways too, to be covered soon).
-- The object referenced by `[[Prototype]]` is called a "prototype".
-- If we want to read a property of `obj` or call a method, and it doesn't exist, then JavaScript tries to find it in the prototype. Write/delete operations work directly on the object, they don't use the prototype (unless the property is actually a setter).
-- If we call `obj.method()`, and the `method` is taken from the prototype, `this` still references `obj`. So methods always work with the current object even if they are inherited.
diff --git a/1-js/07-object-oriented-programming/03-prototype-inheritance/object-prototype-empty.png b/1-js/07-object-oriented-programming/03-prototype-inheritance/object-prototype-empty.png
deleted file mode 100644
index 1d228b5c8a..0000000000
Binary files a/1-js/07-object-oriented-programming/03-prototype-inheritance/object-prototype-empty.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/03-prototype-inheritance/object-prototype-empty@2x.png b/1-js/07-object-oriented-programming/03-prototype-inheritance/object-prototype-empty@2x.png
deleted file mode 100644
index a4c195ad69..0000000000
Binary files a/1-js/07-object-oriented-programming/03-prototype-inheritance/object-prototype-empty@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-animal-rabbit-chain.png b/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-animal-rabbit-chain.png
deleted file mode 100644
index a302343e2d..0000000000
Binary files a/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-animal-rabbit-chain.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-animal-rabbit-chain@2x.png b/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-animal-rabbit-chain@2x.png
deleted file mode 100644
index 4d3311998e..0000000000
Binary files a/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-animal-rabbit-chain@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-animal-rabbit-walk-2.png b/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-animal-rabbit-walk-2.png
deleted file mode 100644
index 19c1881a2f..0000000000
Binary files a/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-animal-rabbit-walk-2.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-animal-rabbit-walk-2@2x.png b/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-animal-rabbit-walk-2@2x.png
deleted file mode 100644
index cd38624ab0..0000000000
Binary files a/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-animal-rabbit-walk-2@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-animal-rabbit-walk-3.png b/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-animal-rabbit-walk-3.png
deleted file mode 100644
index 0ea869d3c5..0000000000
Binary files a/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-animal-rabbit-walk-3.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-animal-rabbit-walk-3@2x.png b/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-animal-rabbit-walk-3@2x.png
deleted file mode 100644
index 194db77edd..0000000000
Binary files a/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-animal-rabbit-walk-3@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-animal-rabbit-walk.png b/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-animal-rabbit-walk.png
deleted file mode 100644
index 5bd2111474..0000000000
Binary files a/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-animal-rabbit-walk.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-animal-rabbit-walk@2x.png b/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-animal-rabbit-walk@2x.png
deleted file mode 100644
index 1e4ef6efbd..0000000000
Binary files a/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-animal-rabbit-walk@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-animal-rabbit.png b/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-animal-rabbit.png
deleted file mode 100644
index c18e020525..0000000000
Binary files a/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-animal-rabbit.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-animal-rabbit@2x.png b/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-animal-rabbit@2x.png
deleted file mode 100644
index 4d9e8ec094..0000000000
Binary files a/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-animal-rabbit@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-user-admin.png b/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-user-admin.png
deleted file mode 100644
index aed69c59e0..0000000000
Binary files a/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-user-admin.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-user-admin@2x.png b/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-user-admin@2x.png
deleted file mode 100644
index 2b11b2568b..0000000000
Binary files a/1-js/07-object-oriented-programming/03-prototype-inheritance/proto-user-admin@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/04-function-prototype/1-changing-prototype/solution.md b/1-js/07-object-oriented-programming/04-function-prototype/1-changing-prototype/solution.md
deleted file mode 100644
index 771e3061c9..0000000000
--- a/1-js/07-object-oriented-programming/04-function-prototype/1-changing-prototype/solution.md
+++ /dev/null
@@ -1,20 +0,0 @@
-
-Answers:
-
-1. `true`.
-
- The assignment to `Rabbit.prototype` sets up `[[Prototype]]` for new objects, but it does not affect the existing ones.
-
-2. `false`.
-
- Objects are assigned by reference. The object from `Rabbit.prototype` is not duplicated, it's still a single object is referenced both by `Rabbit.prototype` and by the `[[Prototype]]` of `rabbit`.
-
- So when we change its content through one reference, it is visible through the other one.
-
-3. `true`.
-
- All `delete` operations are applied directly to the object. Here `delete rabbit.eats` tries to remove `eats` property from `rabbit`, but it doesn't have it. So the operation won't have any effect.
-
-4. `undefined`.
-
- The property `eats` is deleted from the prototype, it doesn't exist any more.
diff --git a/1-js/07-object-oriented-programming/04-function-prototype/1-changing-prototype/task.md b/1-js/07-object-oriented-programming/04-function-prototype/1-changing-prototype/task.md
deleted file mode 100644
index 4b8522d3dd..0000000000
--- a/1-js/07-object-oriented-programming/04-function-prototype/1-changing-prototype/task.md
+++ /dev/null
@@ -1,89 +0,0 @@
-importance: 5
-
----
-
-# Changing "prototype"
-
-In the code below we create `new Rabbit`, and then try to modify its prototype.
-
-In the start, we have this code:
-
-```js run
-function Rabbit() {}
-Rabbit.prototype = {
- eats: true
-};
-
-let rabbit = new Rabbit();
-
-alert( rabbit.eats ); // true
-```
-
-
-1. We added one more string (emphasized), what `alert` shows now?
-
- ```js
- function Rabbit() {}
- Rabbit.prototype = {
- eats: true
- };
-
- let rabbit = new Rabbit();
-
- *!*
- Rabbit.prototype = {};
- */!*
-
- alert( rabbit.eats ); // ?
- ```
-
-2. ...And if the code is like this (replaced one line)?
-
- ```js
- function Rabbit() {}
- Rabbit.prototype = {
- eats: true
- };
-
- let rabbit = new Rabbit();
-
- *!*
- Rabbit.prototype.eats = false;
- */!*
-
- alert( rabbit.eats ); // ?
- ```
-
-3. Like this (replaced one line)?
-
- ```js
- function Rabbit() {}
- Rabbit.prototype = {
- eats: true
- };
-
- let rabbit = new Rabbit();
-
- *!*
- delete rabbit.eats;
- */!*
-
- alert( rabbit.eats ); // ?
- ```
-
-4. The last variant:
-
- ```js
- function Rabbit() {}
- Rabbit.prototype = {
- eats: true
- };
-
- let rabbit = new Rabbit();
-
- *!*
- delete Rabbit.prototype.eats;
- */!*
-
- alert( rabbit.eats ); // ?
- ```
diff --git a/1-js/07-object-oriented-programming/04-function-prototype/4-new-object-same-constructor/solution.md b/1-js/07-object-oriented-programming/04-function-prototype/4-new-object-same-constructor/solution.md
deleted file mode 100644
index 43190e163b..0000000000
--- a/1-js/07-object-oriented-programming/04-function-prototype/4-new-object-same-constructor/solution.md
+++ /dev/null
@@ -1,44 +0,0 @@
-We can use such approach if we are sure that `"constructor"` property has the correct value.
-
-For instance, if we don't touch the default `"prototype"`, then this code works for sure:
-
-```js run
-function User(name) {
- this.name = name;
-}
-
-let user = new User('John');
-let user2 = new user.constructor('Pete');
-
-alert( user2.name ); // Pete (worked!)
-```
-
-It worked, because `User.prototype.constructor == User`.
-
-..But if someone, so to say, overwrites `User.prototype` and forgets to recreate `"constructor"`, then it would fail.
-
-For instance:
-
-```js run
-function User(name) {
- this.name = name;
-}
-*!*
-User.prototype = {}; // (*)
-*/!*
-
-let user = new User('John');
-let user2 = new user.constructor('Pete');
-
-alert( user2.name ); // undefined
-```
-
-Why `user2.name` is `undefined`?
-
-Here's how `new user.constructor('Pete')` works:
-
-1. First, it looks for `constructor` in `user`. Nothing.
-2. Then it follows the prototype chain. The prototype of `user` is `User.prototype`, and it also has nothing.
-3. The value of `User.prototype` is a plain object `{}`, its prototype is `Object.prototype`. And there is `Object.prototype.constructor == Object`. So it is used.
-
-At the end, we have `let user2 = new Object('Pete')`. The built-in `Object` constructor ignores arguments, it always creates an empty object -- that's what we have in `user2` after all.
diff --git a/1-js/07-object-oriented-programming/04-function-prototype/article.md b/1-js/07-object-oriented-programming/04-function-prototype/article.md
deleted file mode 100644
index 27c67e325f..0000000000
--- a/1-js/07-object-oriented-programming/04-function-prototype/article.md
+++ /dev/null
@@ -1,176 +0,0 @@
-# F.prototype
-
-In modern JavaScript we can set a prototype using `__proto__`. But it wasn't like that all the time.
-
-[cut]
-
-JavaScript has had prototypal inheritance from the beginning. It was one of the core features of the language.
-
-But in the old times, there was another (and the only) way to set it: to use a `"prototype"` property of the constructor function. And there are still many scripts that use it.
-
-## The "prototype" property
-
-As we know already, `new F()` creates a new object. But what we didn't use yet `F.prototype` property.
-
-That property is used by the JavaScript itself to set `[[Prototype]]` for new objects.
-
-**When a new object is created with `new F()`, the object's `[[Prototype]]` is set to `F.prototype`.**
-
-Please note that `F.prototype` here means a regular property named `"prototype"` on `F`. It sounds something similar to the term "prototype", but here we really mean a regular property with this name.
-
-Here's the example:
-
-```js run
-let animal = {
- eats: true
-};
-
-function Rabbit(name) {
- this.name = name;
-}
-
-*!*
-Rabbit.prototype = animal;
-*/!*
-
-let rabbit = new Rabbit("White Rabbit"); // rabbit.__proto__ == animal
-
-alert( rabbit.eats ); // true
-```
-
-Setting `Rabbit.prototype = animal` literally states the following: "When a `new Rabbit` is created, assign its `[[Prototype]]` to `animal`".
-
-That's the resulting picture:
-
-
-
-On the picture, `"prototype"` is a horizontal arrow, it's a regular property, and `[[Prototype]]` is vertical, meaning the inheritance of `rabbit` from `animal`.
-
-
-## Default F.prototype, constructor property
-
-Every function has the `"prototype"` property even if we don't supply it.
-
-The default `"prototype"` is an object with the only property `constructor` that points back to the function itself.
-
-Like this:
-
-```js
-function Rabbit() {}
-
-/* default prototype
-Rabbit.prototype = { constructor: Rabbit };
-*/
-```
-
-
-
-We can check it:
-
-```js run
-function Rabbit() {}
-// by default:
-// Rabbit.prototype = { constructor: Rabbit }
-
-alert( Rabbit.prototype.constructor == Rabbit ); // true
-```
-
-Naturally, it we do nothing, the `constructor` property is available to all rabbits through `[[Prototype]]`:
-
-```js run
-function Rabbit() {}
-// by default:
-// Rabbit.prototype = { constructor: Rabbit }
-
-let rabbit = new Rabbit(); // inherits from {constructor: Rabbit}
-
-alert(rabbit.constructor == Rabbit); // true (from prototype)
-```
-
-
-
-We can use `constructor` property to create a new object using the same constructor as the existing one.
-
-Like here:
-
-```js run
-function Rabbit(name) {
- this.name = name;
- alert(name);
-}
-
-let rabbit = new Rabbit("White Rabbit");
-
-*!*
-let rabbit2 = new rabbit.constructor("Black Rabbit");
-*/!*
-```
-
-That's handy when we have an object, don't know which constructor was used for it (e.g. it comes from a 3rd party library), and we need to create another one of the same kind.
-
-But probably the most important thing about `"constructor"` is that...
-
-**...JavaScript itself does not ensure the right `"constructor"` value.**
-
-Yes, it exists in the default `"prototype"` for functions, but that's all. What happens with it later -- is totally on us.
-
-In particular, if we replace the default prototype as a whole, then there will be no `"constructor"` in it.
-
-For instance:
-
-```js run
-function Rabbit() {}
-Rabbit.prototype = {
- jumps: true
-};
-
-let rabbit = new Rabbit();
-*!*
-alert(rabbit.constructor === Rabbit); // false
-*/!*
-```
-
-So, to keep the right `"constructor"` we can choose to add/remove properties to the default `"prototype"` instead of overwriting it as a whole:
-
-```js
-function Rabbit() {}
-
-// Not overwrite Rabbit.prototype totally
-// just add to it
-Rabbit.prototype.jumps = true
-// the default Rabbit.prototype.constructor is preserved
-```
-
-Or, alternatively, recreate the `constructor` property it manually:
-
-```js
-Rabbit.prototype = {
- jumps: true,
-*!*
- constructor: Rabbit
-*/!*
-};
-
-// now constructor is also correct, because we added it
-```
-
-
-## Summary
-
-In this chapter we briefly described the way of setting a `[[Prototype]]` for objects created via a constructor function. Later we'll see more advanced programming patterns that rely on it.
-
-Everything is quite simple, just few notes to make things clear:
-
-- The `F.prototype` property is not the same as `[[Prototype]]`. The only thing `F.prototype` does: it sets `[[Prototype]]` of new objects when `new F()` is called.
-- The value of `F.prototype` should be either an object or null: other values won't work.
-- The `"prototype"` property only has such a special effect when is set to a constructor function, and invoked with `new`.
-
-On regular objects the `prototype` is nothing special:
-```js
-let user = {
- name: "John",
- prototype: "Bla-bla" // no magic at all
-};
-```
-
-By default all functions have `F.prototype = { constructor: F }`, so we can get the constructor of an object by accessing its `"constructor"` property.
diff --git a/1-js/07-object-oriented-programming/04-function-prototype/function-prototype-constructor.png b/1-js/07-object-oriented-programming/04-function-prototype/function-prototype-constructor.png
deleted file mode 100644
index 0dbc7b8fc4..0000000000
Binary files a/1-js/07-object-oriented-programming/04-function-prototype/function-prototype-constructor.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/04-function-prototype/function-prototype-constructor@2x.png b/1-js/07-object-oriented-programming/04-function-prototype/function-prototype-constructor@2x.png
deleted file mode 100644
index e38cb85bd9..0000000000
Binary files a/1-js/07-object-oriented-programming/04-function-prototype/function-prototype-constructor@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/04-function-prototype/native-prototypes-array-tostring.png b/1-js/07-object-oriented-programming/04-function-prototype/native-prototypes-array-tostring.png
deleted file mode 100644
index 83258d0614..0000000000
Binary files a/1-js/07-object-oriented-programming/04-function-prototype/native-prototypes-array-tostring.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/04-function-prototype/native-prototypes-array-tostring@2x.png b/1-js/07-object-oriented-programming/04-function-prototype/native-prototypes-array-tostring@2x.png
deleted file mode 100644
index d77cc8f4ec..0000000000
Binary files a/1-js/07-object-oriented-programming/04-function-prototype/native-prototypes-array-tostring@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/04-function-prototype/native-prototypes-classes.png b/1-js/07-object-oriented-programming/04-function-prototype/native-prototypes-classes.png
deleted file mode 100644
index fa6a2943f6..0000000000
Binary files a/1-js/07-object-oriented-programming/04-function-prototype/native-prototypes-classes.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/04-function-prototype/native-prototypes-classes@2x.png b/1-js/07-object-oriented-programming/04-function-prototype/native-prototypes-classes@2x.png
deleted file mode 100644
index 9368d7e502..0000000000
Binary files a/1-js/07-object-oriented-programming/04-function-prototype/native-prototypes-classes@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/04-function-prototype/object-prototype-1.png b/1-js/07-object-oriented-programming/04-function-prototype/object-prototype-1.png
deleted file mode 100644
index e7c6bdb212..0000000000
Binary files a/1-js/07-object-oriented-programming/04-function-prototype/object-prototype-1.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/04-function-prototype/object-prototype-1@2x.png b/1-js/07-object-oriented-programming/04-function-prototype/object-prototype-1@2x.png
deleted file mode 100644
index 34c256bbfd..0000000000
Binary files a/1-js/07-object-oriented-programming/04-function-prototype/object-prototype-1@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/04-function-prototype/object-prototype.png b/1-js/07-object-oriented-programming/04-function-prototype/object-prototype.png
deleted file mode 100644
index d97d87d2c3..0000000000
Binary files a/1-js/07-object-oriented-programming/04-function-prototype/object-prototype.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/04-function-prototype/object-prototype@2x.png b/1-js/07-object-oriented-programming/04-function-prototype/object-prototype@2x.png
deleted file mode 100644
index 76ce4c9ac5..0000000000
Binary files a/1-js/07-object-oriented-programming/04-function-prototype/object-prototype@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/04-function-prototype/proto-constructor-animal-rabbit.png b/1-js/07-object-oriented-programming/04-function-prototype/proto-constructor-animal-rabbit.png
deleted file mode 100644
index 3eec740fbb..0000000000
Binary files a/1-js/07-object-oriented-programming/04-function-prototype/proto-constructor-animal-rabbit.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/04-function-prototype/proto-constructor-animal-rabbit@2x.png b/1-js/07-object-oriented-programming/04-function-prototype/proto-constructor-animal-rabbit@2x.png
deleted file mode 100644
index ed28a388a0..0000000000
Binary files a/1-js/07-object-oriented-programming/04-function-prototype/proto-constructor-animal-rabbit@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/04-function-prototype/rabbit-animal-object.png b/1-js/07-object-oriented-programming/04-function-prototype/rabbit-animal-object.png
deleted file mode 100644
index 3254270f38..0000000000
Binary files a/1-js/07-object-oriented-programming/04-function-prototype/rabbit-animal-object.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/04-function-prototype/rabbit-animal-object@2x.png b/1-js/07-object-oriented-programming/04-function-prototype/rabbit-animal-object@2x.png
deleted file mode 100644
index f794d7b84a..0000000000
Binary files a/1-js/07-object-oriented-programming/04-function-prototype/rabbit-animal-object@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/04-function-prototype/rabbit-prototype-constructor.png b/1-js/07-object-oriented-programming/04-function-prototype/rabbit-prototype-constructor.png
deleted file mode 100644
index d3ef344852..0000000000
Binary files a/1-js/07-object-oriented-programming/04-function-prototype/rabbit-prototype-constructor.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/04-function-prototype/rabbit-prototype-constructor@2x.png b/1-js/07-object-oriented-programming/04-function-prototype/rabbit-prototype-constructor@2x.png
deleted file mode 100644
index 45cbb6baab..0000000000
Binary files a/1-js/07-object-oriented-programming/04-function-prototype/rabbit-prototype-constructor@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/05-native-prototypes/2-defer-to-prototype-extended/solution.md b/1-js/07-object-oriented-programming/05-native-prototypes/2-defer-to-prototype-extended/solution.md
deleted file mode 100644
index e3651683fa..0000000000
--- a/1-js/07-object-oriented-programming/05-native-prototypes/2-defer-to-prototype-extended/solution.md
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-```js run
-Function.prototype.defer = function(ms) {
- let f = this;
- return function(...args) {
- setTimeout(() => f.apply(this, args), ms);
- }
-};
-
-// check it
-function f(a, b) {
- alert( a + b );
-}
-
-f.defer(1000)(1, 2); // shows 3 after 1 sec
-```
diff --git a/1-js/07-object-oriented-programming/05-native-prototypes/article.md b/1-js/07-object-oriented-programming/05-native-prototypes/article.md
deleted file mode 100644
index 6c29c7f1c9..0000000000
--- a/1-js/07-object-oriented-programming/05-native-prototypes/article.md
+++ /dev/null
@@ -1,180 +0,0 @@
-# Native prototypes
-
-The `"prototype"` property is widely used by the core of JavaScript itself. All built-in constructor functions use it.
-
-We'll see how it is for plain objects first, and then for more complex ones.
-
-## Object.prototype
-
-Let's say we output an empty object:
-
-```js run
-let obj = {};
-alert( obj ); // "[object Object]" ?
-```
-
-Where's the code that generates the string `"[object Object]"`? That's a built-in `toString` method, but where is it? The `obj` is empty!
-
-...But the short notation `obj = {}` is the same as `obj = new Object()`, where `Object` -- is a built-in object constructor function. And that function has `Object.prototype` that references a huge object with `toString` and other functions.
-
-Like this (all that is built-in):
-
-
-
-When `new Object()` is called (or a literal object `{...}` is created), the `[[Prototype]]` of it is set to `Object.prototype` by the rule that we've discussed in the previous chapter:
-
-
-
-Afterwards when `obj.toString()` is called -- the method is taken from `Object.prototype`.
-
-We can check it like this:
-
-```js run
-let obj = {};
-
-alert(obj.__proto__ === Object.prototype); // true
-// obj.toString === obj.__proto__toString == Object.prototype.toString
-```
-
-Please note that there is no additional `[[Prototype]]` in the chain above `Object.prototype`:
-
-```js run
-alert(Object.prototype.__proto__); // null
-```
-
-## Other built-in prototypes
-
-Other built-in objects such as `Array`, `Date`, `Function` and others also keep methods in prototypes.
-
-For instance, when we create an array `[1, 2, 3]`, the default `new Array()` constructor is used internally. So the array data is written into the new object, and `Array.prototype` becomes its prototype and provides methods. That's very memory-efficient.
-
-By specification, all built-in prototypes have `Object.prototype` on the top. Sometimes people say that "everything inherits from objects".
-
-Here's the overall picture (for 3 built-ins to fit):
-
-
-
-Let's check the prototypes manually:
-
-```js run
-let arr = [1, 2, 3];
-
-// it inherits from Array.prototype?
-alert( arr.__proto__ === Array.prototype ); // true
-
-// then from Object.prototype?
-alert( arr.__proto__.__proto__ === Object.prototype ); // true
-
-// and null on the top.
-alert( arr.__proto__.__proto__.__proto__ ); // null
-```
-
-Some methods in prototypes may overlap, for instance, `Array.prototype` has its own `toString` that lists comma-delimited elements:
-
-```js run
-let arr = [1, 2, 3]
-alert(arr); // 1,2,3 <-- the result of Array.prototype.toString
-```
-
-As we've seen before, `Object.prototype` has `toString` as well, but `Array.prototype` is closer in the chain, so the array variant is used.
-
-
-
-
-
-In-browser tools like Chrome developer console also show inheritance (may need to use `console.dir` for built-in objects):
-
-
-
-Other built-in objects also work the same way. Even functions. They are objects of a built-in `Function` constructor, and their methods: `call/apply` and others are taken from `Function.prototype`. Functions have their own `toString` too.
-
-```js run
-function f() {}
-
-alert(f.__proto__ == Function.prototype); // true
-alert(f.__proto__.__proto__ == Object.prototype); // true, inherit from objects
-```
-
-## Primitives
-
-The most intricate thing happens with strings, numbers and booleans.
-
-As we remember, they are not objects. But if we try to access their properties, then temporary wrapper objects are created using built-in constructors `String`, `Number`, `Boolean`, they provide the methods and disappear.
-
-These objects are created invisibly to us and most engines optimize them out, but the specification describes it exactly this way. Methods of these objects also reside in prototypes, available as `String.prototype`, `Number.prototype` and `Boolean.prototype`.
-
-```warn header="Values `null` and `undefined` have no object wrappers"
-Special values `null` and `undefined` stand apart. They have no object wrappers, so methods and properties are not available for them. And there are no corresponding prototypes too.
-```
-
-## Changing native prototypes [#native-prototype-change]
-
-Native prototypes can be modified. For instance, if we add a method to `String.prototype`, it becomes available to all strings:
-
-```js run
-String.prototype.show = function() {
- alert(this);
-};
-
-"BOOM!".show(); // BOOM!
-```
-
-During the process of development we may have ideas which new built-in methods we'd like to have. And there may be a slight temptation to add them to native prototypes. But that is generally a bad idea.
-
-Prototypes are global, so it's easy to get a conflict. If two libraries add a method `String.prototype.show`, then one of them overwrites the other one.
-
-In modern programming, there is only one case when modifying native prototypes is approved. That's polyfills. In other words, if there's a method in JavaScript specification that is not yet supported by our JavaScript engine (or any of those that we want to support), then may implement it manually and populate the built-in prototype with it.
-
-For instance:
-
-```js run
-if (!String.prototype.repeat) { // if there's no such method
- // add it to the prototype
-
- String.prototype.repeat = function(n) {
- // repeat the string n times
-
- // actually, the code should be more complex than that,
- // throw errors for negative values of "n"
- // the full algorithm is in the specification
- return new Array(n + 1).join(this);
- };
-}
-
-alert( "La".repeat(3) ); // LaLaLa
-```
-
-## Borrowing from prototypes
-
-In the chapter we talked about method borrowing:
-
-```js run
-function showArgs() {
-*!*
- // borrow join from array and call in the context of arguments
- alert( [].join.call(arguments, " - ") );
-*/!*
-}
-
-showArgs("John", "Pete", "Alice"); // John - Pete - Alice
-```
-
-Because `join` resides in `Array.prototype`, we can call it from there directly and rewrite it as:
-
-```js
-function showArgs() {
-*!*
- alert( Array.prototype.join.call(arguments, " - ") );
-*/!*
-}
-```
-
-That's more efficient, because it avoids the creation of an extra array object `[]`. On the other hand, it is longer to write.
-
-## Summary
-
-- All built-in objects follow the same pattern:
- - The methods are stored in the prototype (`Array.prototype`, `Object.prototype`, `Date.prototype` etc).
- - The object itself stores only the data (array items, object properties, the date).
-- Primitives also store methods in prototypes of wrapper objects: `Number.prototype`, `String.prototype`, `Boolean.prototype`. There are no wrapper objects only for `undefined` and `null`.
-- Built-in prototypes can be modified or populated with new methods. But it's not recommended to change them. Probably the only allowable cause is when we add-in a new standard, but not yet supported by the engine JavaScript method.
diff --git a/1-js/07-object-oriented-programming/05-native-prototypes/function-prototype-constructor.png b/1-js/07-object-oriented-programming/05-native-prototypes/function-prototype-constructor.png
deleted file mode 100644
index 0dbc7b8fc4..0000000000
Binary files a/1-js/07-object-oriented-programming/05-native-prototypes/function-prototype-constructor.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/05-native-prototypes/function-prototype-constructor@2x.png b/1-js/07-object-oriented-programming/05-native-prototypes/function-prototype-constructor@2x.png
deleted file mode 100644
index e38cb85bd9..0000000000
Binary files a/1-js/07-object-oriented-programming/05-native-prototypes/function-prototype-constructor@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/05-native-prototypes/native-prototypes-array-tostring.png b/1-js/07-object-oriented-programming/05-native-prototypes/native-prototypes-array-tostring.png
deleted file mode 100644
index 83258d0614..0000000000
Binary files a/1-js/07-object-oriented-programming/05-native-prototypes/native-prototypes-array-tostring.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/05-native-prototypes/native-prototypes-array-tostring@2x.png b/1-js/07-object-oriented-programming/05-native-prototypes/native-prototypes-array-tostring@2x.png
deleted file mode 100644
index d77cc8f4ec..0000000000
Binary files a/1-js/07-object-oriented-programming/05-native-prototypes/native-prototypes-array-tostring@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/05-native-prototypes/native-prototypes-classes.png b/1-js/07-object-oriented-programming/05-native-prototypes/native-prototypes-classes.png
deleted file mode 100644
index fa6a2943f6..0000000000
Binary files a/1-js/07-object-oriented-programming/05-native-prototypes/native-prototypes-classes.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/05-native-prototypes/native-prototypes-classes@2x.png b/1-js/07-object-oriented-programming/05-native-prototypes/native-prototypes-classes@2x.png
deleted file mode 100644
index 9368d7e502..0000000000
Binary files a/1-js/07-object-oriented-programming/05-native-prototypes/native-prototypes-classes@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/05-native-prototypes/object-prototype-1.png b/1-js/07-object-oriented-programming/05-native-prototypes/object-prototype-1.png
deleted file mode 100644
index e7c6bdb212..0000000000
Binary files a/1-js/07-object-oriented-programming/05-native-prototypes/object-prototype-1.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/05-native-prototypes/object-prototype-1@2x.png b/1-js/07-object-oriented-programming/05-native-prototypes/object-prototype-1@2x.png
deleted file mode 100644
index 34c256bbfd..0000000000
Binary files a/1-js/07-object-oriented-programming/05-native-prototypes/object-prototype-1@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/05-native-prototypes/object-prototype-null.png b/1-js/07-object-oriented-programming/05-native-prototypes/object-prototype-null.png
deleted file mode 100644
index 7c2e3f9c78..0000000000
Binary files a/1-js/07-object-oriented-programming/05-native-prototypes/object-prototype-null.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/05-native-prototypes/object-prototype-null@2x.png b/1-js/07-object-oriented-programming/05-native-prototypes/object-prototype-null@2x.png
deleted file mode 100644
index fec1facb0b..0000000000
Binary files a/1-js/07-object-oriented-programming/05-native-prototypes/object-prototype-null@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/05-native-prototypes/object-prototype.png b/1-js/07-object-oriented-programming/05-native-prototypes/object-prototype.png
deleted file mode 100644
index d97d87d2c3..0000000000
Binary files a/1-js/07-object-oriented-programming/05-native-prototypes/object-prototype.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/05-native-prototypes/object-prototype@2x.png b/1-js/07-object-oriented-programming/05-native-prototypes/object-prototype@2x.png
deleted file mode 100644
index 76ce4c9ac5..0000000000
Binary files a/1-js/07-object-oriented-programming/05-native-prototypes/object-prototype@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/05-native-prototypes/proto-constructor-animal-rabbit.png b/1-js/07-object-oriented-programming/05-native-prototypes/proto-constructor-animal-rabbit.png
deleted file mode 100644
index 3eec740fbb..0000000000
Binary files a/1-js/07-object-oriented-programming/05-native-prototypes/proto-constructor-animal-rabbit.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/05-native-prototypes/proto-constructor-animal-rabbit@2x.png b/1-js/07-object-oriented-programming/05-native-prototypes/proto-constructor-animal-rabbit@2x.png
deleted file mode 100644
index ed28a388a0..0000000000
Binary files a/1-js/07-object-oriented-programming/05-native-prototypes/proto-constructor-animal-rabbit@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/05-native-prototypes/rabbit-prototype-constructor.png b/1-js/07-object-oriented-programming/05-native-prototypes/rabbit-prototype-constructor.png
deleted file mode 100644
index d3ef344852..0000000000
Binary files a/1-js/07-object-oriented-programming/05-native-prototypes/rabbit-prototype-constructor.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/05-native-prototypes/rabbit-prototype-constructor@2x.png b/1-js/07-object-oriented-programming/05-native-prototypes/rabbit-prototype-constructor@2x.png
deleted file mode 100644
index 45cbb6baab..0000000000
Binary files a/1-js/07-object-oriented-programming/05-native-prototypes/rabbit-prototype-constructor@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/06-prototype-methods/2-dictionary-tostring/solution.md b/1-js/07-object-oriented-programming/06-prototype-methods/2-dictionary-tostring/solution.md
deleted file mode 100644
index debaecd6a1..0000000000
--- a/1-js/07-object-oriented-programming/06-prototype-methods/2-dictionary-tostring/solution.md
+++ /dev/null
@@ -1,29 +0,0 @@
-
-The method can take all enumerable keys using `Object.keys` and output their list.
-
-To make `toString` non-enumerable, let's define it using a property descriptor. The syntax of `Object.create` allows to provide an object with property descriptors as the second argument.
-
-```js run
-*!*
-let dictionary = Object.create(null, {
- toString: { // define toString property
- value() { // the value is a function
- return Object.keys(this).join();
- }
- }
-});
-*/!*
-
-dictionary.apple = "Apple";
-dictionary.__proto__ = "test";
-
-// apple and __proto__ is in the loop
-for(let key in dictionary) {
- alert(key); // "apple", then "__proto__"
-}
-
-// comma-separated list of properties by toString
-alert(dictionary); // "apple,__proto__"
-```
-
-When we create a property using a descriptor, its flags are `false` by default. So in the code above, `dictionary.toString` is non-enumerable.
diff --git a/1-js/07-object-oriented-programming/06-prototype-methods/3-compare-calls/task.md b/1-js/07-object-oriented-programming/06-prototype-methods/3-compare-calls/task.md
deleted file mode 100644
index 92653bd8c3..0000000000
--- a/1-js/07-object-oriented-programming/06-prototype-methods/3-compare-calls/task.md
+++ /dev/null
@@ -1,27 +0,0 @@
-importance: 5
-
----
-
-# The difference beteeen calls
-
-Let's create a new `rabbit` object:
-
-```js
-function Rabbit(name) {
- this.name = name;
-}
-Rabbit.prototype.sayHi = function() {
- alert(this.name);
-};
-
-let rabbit = new Rabbit("Rabbit");
-```
-
-These calls do the same thing or not?
-
-```js
-rabbit.sayHi();
-Rabbit.prototype.sayHi();
-Object.getPrototypeOf(rabbit).sayHi();
-rabbit.__proto__.sayHi();
-```
diff --git a/1-js/07-object-oriented-programming/06-prototype-methods/article.md b/1-js/07-object-oriented-programming/06-prototype-methods/article.md
deleted file mode 100644
index ec14fd4820..0000000000
--- a/1-js/07-object-oriented-programming/06-prototype-methods/article.md
+++ /dev/null
@@ -1,255 +0,0 @@
-
-# Methods for prototypes
-
-In this chapter we cover additional methods to work with a prototype.
-
-There are also other ways to get/set a prototype, besides those that we already know:
-
-- [Object.create(proto[, descriptors])](mdn:js/Object/create) -- creates an empty object with given `proto` as `[[Prototype]]` and optional property descriptors.
-- [Object.getPrototypeOf(obj)](mdn:js/Object.getPrototypeOf) -- returns the `[[Prototype]]` of `obj`.
-- [Object.setPrototypeOf(obj, proto)](mdn:js/Object.setPrototypeOf) -- sets the `[[Prototype]]` of `obj` to `proto`.
-
-[cut]
-
-For instance:
-
-```js run
-let animal = {
- eats: true
-};
-
-// create a new object with animal as a prototype
-*!*
-let rabbit = Object.create(animal);
-*/!*
-
-alert(rabbit.eats); // true
-*!*
-alert(Object.getPrototypeOf(rabbit) === animal); // get the prototype of rabbit
-*/!*
-
-*!*
-Object.setPrototypeOf(rabbit, {}); // change the prototype of rabbit to {}
-*/!*
-```
-
-`Object.create` has an optional second argument: property descriptors. We can provide additional properties to the new object there, like this:
-
-```js run
-let animal = {
- eats: true
-};
-
-let rabbit = Object.create(animal, {
- jumps: {
- value: true
- }
-});
-
-alert(rabbit.jumps); // true
-```
-
-The descriptors are in the same format as described in the chapter .
-
-We can use `Object.create` to perform a full object cloning, like this:
-
-```js
-// fully identical shallow clone of obj
-let clone = Object.create(obj, Object.getOwnPropertyDescriptors(obj));
-```
-
-This call makes a truly exact copy of `obj`, including all properties: enumerable and non-enumerable, data properties and setters/getters -- everything, and with the right `[[Prototype]]`. But not an in-depth copy of course.
-
-## Brief history
-
-If we count all the ways to manage `[[Prototype]]`, there's a lot! Many ways to do the same!
-
-Why so?
-
-That's for historical reasons.
-
-- The `"prototype"` property of a constructor function works since very ancient times.
-- Later in the year 2012: `Object.create` appeared in the standard. It allowed to create objects with the given prototype, but did not allow to get/set it. So browsers implemented non-standard `__proto__` accessor that allowed to get/set a prototype at any time.
-- Later in the year 2015: `Object.setPrototypeOf` and `Object.getPrototypeOf` were added to the standard. The `__proto__` was de-facto implemented everywhere, so it made its way to the Annex B of the standard, that is optional for non-browser environments.
-
-As of now we have all these ways at our disposal.
-
-Technically, we can get/set `[[Prototype]]` at any time. But usually we only set it once at the object creation time, and then do not modify: `rabbit` inherits from `animal`, and that is not going to change. And JavaScript engines are highly optimized to that. Changing a prototype "on-the-fly" with `Object.setPrototypeOf` or `obj.__proto__=` is a very slow operation. But it is possible.
-
-## "Very plain" objects
-
-As we know, objects can be used as associative arrays to store key/value pairs.
-
-...But if we try to store *user-provided* keys in it (for instance, a user-entered dictionary), we can see an interesting glitch: all keys work fine except `"__proto__"`.
-
-Check out the example:
-
-```js run
-let obj = {};
-
-let key = prompt("What's the key?", "__proto__");
-obj[key] = "some value";
-
-alert(obj[key]); // [object Object], not "some value"!
-```
-
-Here if the user types in `__proto__`, the assignment is ignored!
-
-That shouldn't surprise us. The `__proto__` property is special: it must be either an object or `null`, a string can not become a prototype.
-
-But we did not intend to implement such behavior, right? We want to store key/value pairs, and the key named `"__proto__"` was not properly saved. So that's a bug. Here the consequences are not terrible. But in other cases the prototype may indeed be changed, so the execution may go wrong in totally unexpected ways.
-
-What's worst -- usually developers do not think about such possibility at all. That makes such bugs hard to notice and even turn them into vulnerabilities, especially when JavaScript is used on server-side.
-
-Such thing happens only with `__proto__`. All other properties are "assignable" normally.
-
-How to evade the problem?
-
-First, we can just switch to using `Map`, then everything's fine.
-
-But `Object` also can serve us well here, because language creators gave a thought to that problem long ago.
-
-The `__proto__` is not a property of an object, but an accessor property of `Object.prototype`:
-
-
-
-So, if `obj.__proto__` is read or assigned, the corresponding getter/setter is called from its prototype, and it gets/sets `[[Prototype]]`.
-
-As it was said in the beginning: `__proto__` is a way to access `[[Prototype]]`, it is not `[[Prototype]]` itself.
-
-Now, if we want to use an object as an associative array, we can do it with a little trick:
-
-```js run
-*!*
-let obj = Object.create(null);
-*/!*
-
-let key = prompt("What's the key?", "__proto__");
-obj[key] = "some value";
-
-alert(obj[key]); // "some value"
-```
-
-`Object.create(null)` creates an empty object without a prototype (`[[Prototype]]` is `null`):
-
-
-
-So, there is no inherited getter/setter for `__proto__`. Now it is processed as a regular data property, so the example above works right.
-
-We can call such object "very plain" or "pure dictionary objects", because they are even simpler than regular plain object `{...}`.
-
-A downside is that such objects lack any built-in object methods, e.g. `toString`:
-
-```js run
-*!*
-let obj = Object.create(null);
-*/!*
-
-alert(obj); // Error (no toString)
-```
-
-...But that's usually fine for associative arrays.
-
-Please note that most object-related methods are `Object.something(...)`, like `Object.keys(obj)` -- they are not in the prototype, so they will keep working on such objects:
-
-
-```js run
-let chineseDictionary = Object.create(null);
-chineseDictionary.hello = "ni hao";
-chineseDictionary.bye = "zai jian";
-
-alert(Object.keys(chineseDictionary)); // hello,bye
-```
-
-## Getting all properties
-
-There are many ways to get keys/values from an object.
-
-We already know these ones:
-
-- [Object.keys(obj)](mdn:js/Object/keys) / [Object.values(obj)](mdn:js/Object/values) / [Object.entries(obj)](mdn:js/Object/entries) -- returns an array of enumerable own string property names/values/key-value pairs. These methods only list *enumerable* properties, and those that have *strings as keys*.
-
-If we want symbolic properties:
-
-- [Object.getOwnPropertySymbols(obj)](mdn:js/Object/getOwnPropertySymbols) -- returns an array of all own symbolic property names.
-
-If we want non-enumerable properties:
-
-- [Object.getOwnPropertyNames(obj)](mdn:js/Object/getOwnPropertyNames) -- returns an array of all own string property names.
-
-If we want *all* properties:
-
-- [Reflect.ownKeys(obj)](mdn:js/Reflect/ownKeys) -- returns an array of all own property names.
-
-These methods are a bit different about which properties they return, but all of them operate on the object itself. Properties from the prototype are not listed.
-
-The `for..in` loop is different: it loops over inherited properties too.
-
-For instance:
-
-```js run
-let animal = {
- eats: true
-};
-
-let rabbit = {
- jumps: true,
- __proto__: animal
-};
-
-*!*
-// only own keys
-alert(Object.keys(rabbit)); // jumps
-*/!*
-
-*!*
-// inherited keys too
-for(let prop in rabbit) alert(prop); // jumps, then eats
-*/!*
-```
-
-If we want to distinguish inherited properties, there's a built-in method [obj.hasOwnProperty(key)](mdn:js/Object/hasOwnProperty): it returns `true` if `obj` has its own (not inherited) property named `key`.
-
-So we can filter out inherited properties (or do something else with them):
-
-```js run
-let animal = {
- eats: true
-};
-
-let rabbit = {
- jumps: true,
- __proto__: animal
-};
-
-for(let prop in rabbit) {
- let isOwn = rabbit.hasOwnProperty(prop);
- alert(`${prop}: ${isOwn}`); // jumps:true, then eats:false
-}
-```
-Here we have the following inheritance chain: `rabbit`, then `animal`, then `Object.prototype` (because `animal` is a literal object `{...}`, so it's by default), and then `null` above it:
-
-
-
-Note, there's one funny thing. Where is the method `rabbit.hasOwnProperty` coming from? Looking at the chain we can see that the method is provided by `Object.prototype.hasOwnProperty`. In other words, it's inherited.
-
-...But why `hasOwnProperty` does not appear in `for..in` loop, if it lists all inherited properties? The answer is simple: it's not enumerable. Just like all other properties of `Object.prototype`. That's why they are not listed.
-
-## Summary
-
-Here's a brief list of methods we discussed in this chapter -- as a recap:
-
-- [Object.create(proto[, descriptors])](mdn:js/Object/create) -- creates an empty object with given `proto` as `[[Prototype]]` (can be `null`) and optional property descriptors.
-- [Object.getPrototypeOf(obj)](mdn:js/Object.getPrototypeOf) -- returns the `[[Prototype]]` of `obj` (same as `__proto__` getter).
-- [Object.setPrototypeOf(obj, proto)](mdn:js/Object.setPrototypeOf) -- sets the `[[Prototype]]` of `obj` to `proto` (same as `__proto__` setter).
-- [Object.keys(obj)](mdn:js/Object/keys) / [Object.values(obj)](mdn:js/Object/values) / [Object.entries(obj)](mdn:js/Object/entries) -- returns an array of enumerable own string property names/values/key-value pairs.
-- [Object.getOwnPropertySymbols(obj)](mdn:js/Object/getOwnPropertySymbols) -- returns an array of all own symbolic property names.
-- [Object.getOwnPropertyNames(obj)](mdn:js/Object/getOwnPropertyNames) -- returns an array of all own string property names.
-- [Reflect.ownKeys(obj)](mdn:js/Reflect/ownKeys) -- returns an array of all own property names.
-- [obj.hasOwnProperty(key)](mdn:js/Object/hasOwnProperty): it returns `true` if `obj` has its own (not inherited) property named `key`.
-
-We also made it clear that `__proto__` is a getter/setter for `[[Prototype]]` and resides in `Object.prototype`, just as other methods.
-
-We can create an object without a prototype by `Object.create(null)`. Such objects are used as "pure dictionaries", they have no issues with `"__proto__"` as the key.
-
-All methods that return object properties (like `Object.keys` and others) -- return "own" properties. If we want inherited ones, then we can use `for..in`.
diff --git a/1-js/07-object-oriented-programming/06-prototype-methods/object-prototype-2.png b/1-js/07-object-oriented-programming/06-prototype-methods/object-prototype-2.png
deleted file mode 100644
index ee42f6b98c..0000000000
Binary files a/1-js/07-object-oriented-programming/06-prototype-methods/object-prototype-2.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/06-prototype-methods/object-prototype-2@2x.png b/1-js/07-object-oriented-programming/06-prototype-methods/object-prototype-2@2x.png
deleted file mode 100644
index 1917c6631d..0000000000
Binary files a/1-js/07-object-oriented-programming/06-prototype-methods/object-prototype-2@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/06-prototype-methods/object-prototype-null.png b/1-js/07-object-oriented-programming/06-prototype-methods/object-prototype-null.png
deleted file mode 100644
index 7c2e3f9c78..0000000000
Binary files a/1-js/07-object-oriented-programming/06-prototype-methods/object-prototype-null.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/06-prototype-methods/object-prototype-null@2x.png b/1-js/07-object-oriented-programming/06-prototype-methods/object-prototype-null@2x.png
deleted file mode 100644
index fec1facb0b..0000000000
Binary files a/1-js/07-object-oriented-programming/06-prototype-methods/object-prototype-null@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/06-prototype-methods/rabbit-animal-object.png b/1-js/07-object-oriented-programming/06-prototype-methods/rabbit-animal-object.png
deleted file mode 100644
index 3254270f38..0000000000
Binary files a/1-js/07-object-oriented-programming/06-prototype-methods/rabbit-animal-object.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/06-prototype-methods/rabbit-animal-object@2x.png b/1-js/07-object-oriented-programming/06-prototype-methods/rabbit-animal-object@2x.png
deleted file mode 100644
index f794d7b84a..0000000000
Binary files a/1-js/07-object-oriented-programming/06-prototype-methods/rabbit-animal-object@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/08-class-patterns/1-inheritance-error-assign/solution.md b/1-js/07-object-oriented-programming/08-class-patterns/1-inheritance-error-assign/solution.md
deleted file mode 100644
index 55f945ca5d..0000000000
--- a/1-js/07-object-oriented-programming/08-class-patterns/1-inheritance-error-assign/solution.md
+++ /dev/null
@@ -1,46 +0,0 @@
-Here's the line with the error:
-
-```js
-Rabbit.prototype = Animal.prototype;
-```
-
-Here `Rabbit.prototype` and `Animal.prototype` become the same object. So methods of both classes become mixed in that object.
-
-As a result, `Rabbit.prototype.walk` overwrites `Animal.prototype.walk`, so all animals start to bounce:
-
-```js run
-function Animal(name) {
- this.name = name;
-}
-
-Animal.prototype.walk = function() {
- alert(this.name + ' walks');
-};
-
-function Rabbit(name) {
- this.name = name;
-}
-
-*!*
-Rabbit.prototype = Animal.prototype;
-*/!*
-
-Rabbit.prototype.walk = function() {
- alert(this.name + " bounces!");
-};
-
-*!*
-let animal = new Animal("pig");
-animal.walk(); // pig bounces!
-*/!*
-```
-
-The correct variant would be:
-
-```js
-Rabbit.prototype.__proto__ = Animal.prototype;
-// or like this:
-Rabbit.prototype = Object.create(Animal.prototype);
-```
-
-That makes prototypes separate, each of them stores methods of the corresponding class, but `Rabbit.prototype` inherits from `Animal.prototype`.
diff --git a/1-js/07-object-oriented-programming/08-class-patterns/1-inheritance-error-assign/task.md b/1-js/07-object-oriented-programming/08-class-patterns/1-inheritance-error-assign/task.md
deleted file mode 100644
index ee486c3d67..0000000000
--- a/1-js/07-object-oriented-programming/08-class-patterns/1-inheritance-error-assign/task.md
+++ /dev/null
@@ -1,29 +0,0 @@
-importance: 5
-
----
-
-# An error in the inheritance
-
-Find an error in the prototypal inheritance below.
-
-What's wrong? What are consequences going to be?
-
-```js
-function Animal(name) {
- this.name = name;
-}
-
-Animal.prototype.walk = function() {
- alert(this.name + ' walks');
-};
-
-function Rabbit(name) {
- this.name = name;
-}
-
-Rabbit.prototype = Animal.prototype;
-
-Rabbit.prototype.walk = function() {
- alert(this.name + " bounces!");
-};
-```
diff --git a/1-js/07-object-oriented-programming/08-class-patterns/2-rewrite-to-prototypes/solution.md b/1-js/07-object-oriented-programming/08-class-patterns/2-rewrite-to-prototypes/solution.md
deleted file mode 100644
index 300b25d94c..0000000000
--- a/1-js/07-object-oriented-programming/08-class-patterns/2-rewrite-to-prototypes/solution.md
+++ /dev/null
@@ -1 +0,0 @@
-Please note that properties that were internal in functional style (`template`, `timer`) and the internal method `render` are marked private with the underscore `_`.
diff --git a/1-js/07-object-oriented-programming/08-class-patterns/2-rewrite-to-prototypes/solution.view/clock.js b/1-js/07-object-oriented-programming/08-class-patterns/2-rewrite-to-prototypes/solution.view/clock.js
deleted file mode 100644
index 7a193b79d0..0000000000
--- a/1-js/07-object-oriented-programming/08-class-patterns/2-rewrite-to-prototypes/solution.view/clock.js
+++ /dev/null
@@ -1,32 +0,0 @@
-function Clock({ template }) {
- this._template = template;
-}
-
-Clock.prototype._render = function() {
- let date = new Date();
-
- let hours = date.getHours();
- if (hours < 10) hours = '0' + hours;
-
- let mins = date.getMinutes();
- if (mins < 10) min = '0' + mins;
-
- let secs = date.getSeconds();
- if (secs < 10) secs = '0' + secs;
-
- let output = this._template
- .replace('h', hours)
- .replace('m', mins)
- .replace('s', secs);
-
- console.log(output);
-};
-
-Clock.prototype.stop = function() {
- clearInterval(this._timer);
-};
-
-Clock.prototype.start = function() {
- this._render();
- this._timer = setInterval(() => this._render(), 1000);
-};
diff --git a/1-js/07-object-oriented-programming/08-class-patterns/2-rewrite-to-prototypes/solution.view/index.html b/1-js/07-object-oriented-programming/08-class-patterns/2-rewrite-to-prototypes/solution.view/index.html
deleted file mode 100644
index fdee13d01b..0000000000
--- a/1-js/07-object-oriented-programming/08-class-patterns/2-rewrite-to-prototypes/solution.view/index.html
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
- Console clock
-
-
-
-
-
-
-
-
-
-
diff --git a/1-js/07-object-oriented-programming/08-class-patterns/2-rewrite-to-prototypes/source.view/clock.js b/1-js/07-object-oriented-programming/08-class-patterns/2-rewrite-to-prototypes/source.view/clock.js
deleted file mode 100644
index 26081a35a1..0000000000
--- a/1-js/07-object-oriented-programming/08-class-patterns/2-rewrite-to-prototypes/source.view/clock.js
+++ /dev/null
@@ -1,34 +0,0 @@
-function Clock({ template }) {
-
- let timer;
-
- function render() {
- let date = new Date();
-
- let hours = date.getHours();
- if (hours < 10) hours = '0' + hours;
-
- let mins = date.getMinutes();
- if (mins < 10) min = '0' + mins;
-
- let secs = date.getSeconds();
- if (secs < 10) secs = '0' + secs;
-
- let output = template
- .replace('h', hours)
- .replace('m', mins)
- .replace('s', secs);
-
- console.log(output);
- }
-
- this.stop = function() {
- clearInterval(timer);
- };
-
- this.start = function() {
- render();
- timer = setInterval(render, 1000);
- };
-
-}
diff --git a/1-js/07-object-oriented-programming/08-class-patterns/2-rewrite-to-prototypes/source.view/index.html b/1-js/07-object-oriented-programming/08-class-patterns/2-rewrite-to-prototypes/source.view/index.html
deleted file mode 100644
index fdee13d01b..0000000000
--- a/1-js/07-object-oriented-programming/08-class-patterns/2-rewrite-to-prototypes/source.view/index.html
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
- Console clock
-
-
-
-
-
-
-
-
-
-
diff --git a/1-js/07-object-oriented-programming/08-class-patterns/2-rewrite-to-prototypes/task.md b/1-js/07-object-oriented-programming/08-class-patterns/2-rewrite-to-prototypes/task.md
deleted file mode 100644
index 71131816be..0000000000
--- a/1-js/07-object-oriented-programming/08-class-patterns/2-rewrite-to-prototypes/task.md
+++ /dev/null
@@ -1,9 +0,0 @@
-importance: 5
-
----
-
-# Rewrite to prototypes
-
-The `Clock` class is written in functional style. Rewrite it using prototypes.
-
-P.S. The clock ticks in the console, open it to see.
diff --git a/1-js/07-object-oriented-programming/08-class-patterns/article.md b/1-js/07-object-oriented-programming/08-class-patterns/article.md
deleted file mode 100644
index 83c312a25e..0000000000
--- a/1-js/07-object-oriented-programming/08-class-patterns/article.md
+++ /dev/null
@@ -1,243 +0,0 @@
-
-# Class patterns
-
-```quote author="Wikipedia"
-In object-oriented programming, a *class* is an extensible program-code-template for creating objects, providing initial values for state (member variables) and implementations of behavior (member functions or methods).
-```
-
-There's a special syntax construct and a keyword `class` in JavaScript. But before studying it, we should consider that the term "class" comes the theory of object-oriented programming. The definition is cited above, and it's language-independant.
-
-In JavaScript there are several well-known programming patterns to make classes even without using the `class` keyword. And here we'll talk about them first.
-
-The `class` construct will be described in the next chapter, but in JavaScript it's a "syntax sugar" and an extension of one of the patterns that we'll study here.
-
-[cut]
-
-
-## Functional class pattern
-
-The constructor function below can be considered a "class" according to the definition:
-
-```js run
-function User(name) {
- this.sayHi = function() {
- alert(name);
- };
-}
-
-let user = new User("John");
-user.sayHi(); // John
-```
-
-It follows all parts of the definition:
-
-1. It is a "program-code-template" for creating objects (callable with `new`).
-2. It provides initial values for the state (`name` from parameters).
-3. It provides methods (`sayHi`).
-
-This is called *functional class pattern*.
-
-In the functional class pattern, local variables and nested functions inside `User`, that are not assigned to `this`, are visible from inside, but not accessible by the outer code.
-
-So we can easily add internal functions and variables, like `calcAge()` here:
-
-```js run
-function User(name, birthday) {
-
-*!*
- // only visible from other methods inside User
- function calcAge() {
- return new Date().getFullYear() - birthday.getFullYear();
- }
-*/!*
-
- this.sayHi = function() {
- alert(name + ', age:' + calcAge());
- };
-}
-
-let user = new User("John", new Date(2000,0,1));
-user.sayHi(); // John
-```
-
-In this code variables `name`, `birthday` and the function `calcAge()` are internal, *private* to the object. They are only visible from inside of it.
-
-From the other hand, `sayHi` is the external, *public* method. The external code that creates `user` can access it.
-
-This way we can hide internal implementation details and helper methods from the outer code. Only what's assigned to `this` becomes visible outside.
-
-## Factory class pattern
-
-We can create a class without using `new` at all.
-
-Like this:
-
-```js run
-function User(name, birthday) {
- // only visible from other methods inside User
- function calcAge() {
- return new Date().getFullYear() - birthday.getFullYear();
- }
-
- return {
- sayHi() {
- alert(name + ', age:' + calcAge());
- }
- };
-}
-
-*!*
-let user = User("John", new Date(2000,0,1));
-*/!*
-user.sayHi(); // John
-```
-
-As we can see, the function `User` returns an object with public properties and methods. The only benefit of this method is that we can omit `new`: write `let user = User(...)` instead of `let user = new User(...)`. In other aspects it's almost the same as the functional pattern.
-
-## Prototype-based classes
-
-Prototype-based classes is the most important and generally the best. Functional and factory class patterns are rarely used in practice.
-
-Soon you'll see why.
-
-Here's the same class rewritten using prototypes:
-
-```js run
-function User(name, birthday) {
-*!*
- this._name = name;
- this._birthday = birthday;
-*/!*
-}
-
-*!*
-User.prototype._calcAge = function() {
-*/!*
- return new Date().getFullYear() - this._birthday.getFullYear();
-};
-
-User.prototype.sayHi = function() {
- alert(this._name + ', age:' + this._calcAge());
-};
-
-let user = new User("John", new Date(2000,0,1));
-user.sayHi(); // John
-```
-
-The code structure:
-
-- The constructor `User` only initializes the current object state.
-- Methods are added to `User.prototype`.
-
-As we can see, methods are lexically not inside `function User`, they do not share a common lexical environment. If we declare variables inside `function User`, then they won't be visible to methods.
-
-So, there is a widely known agreement that internal properties and methods are prepended with an underscore `"_"`. Like `_name` or `_calcAge()`. Technically, that's just an agreement, the outer code still can access them. But most developers recognize the meaning of `"_"` and try not to touch prefixed properties and methods in the external code.
-
-Here are the advantages over the functional pattern:
-
-- In the functional pattern, each object has its own copy of every method. We assign a separate copy of `this.sayHi = function() {...}` and other methods in the constructor.
-- In the prototypal pattern, all methods are in `User.prototype` that is shared between all user objects. An object itself only stores the data.
-
-So the prototypal pattern is more memory-efficient.
-
-...But not only that. Prototypes allow us to setup the inheritance in a really efficient way. Built-in JavaScript objects all use prototypes. Also there's a special syntax construct: "class" that provides nice-looking syntax for them. And there's more, so let's go on with them.
-
-## Prototype-based inheritance for classes
-
-Let's say we have two prototype-based classes.
-
-`Rabbit`:
-
-```js
-function Rabbit(name) {
- this.name = name;
-}
-
-Rabbit.prototype.jump = function() {
- alert(this.name + ' jumps!');
-};
-
-let rabbit = new Rabbit("My rabbit");
-```
-
-
-
-...And `Animal`:
-
-```js
-function Animal(name) {
- this.name = name;
-}
-
-Animal.prototype.eat = function() {
- alert(this.name + ' eats.');
-};
-
-let animal = new Animal("My animal");
-```
-
-
-
-Right now they are fully independent.
-
-But we'd want `Rabbit` to extend `Animal`. In other words, rabbits should be based on animals, have access to methods of `Animal` and extend them with its own methods.
-
-What does it mean in the language on prototypes?
-
-Right now methods for `rabbit` objects are in `Rabbit.prototype`. We'd like `rabbit` to use `Animal.prototype` as a "fallback", if the method is not found in `Rabbit.prototype`.
-
-So the prototype chain should be `rabbit` -> `Rabbit.prototype` -> `Animal.prototype`.
-
-Like this:
-
-
-
-The code to implement that:
-
-```js run
-// Same Animal as before
-function Animal(name) {
- this.name = name;
-}
-
-// All animals can eat, right?
-Animal.prototype.eat = function() {
- alert(this.name + ' eats.');
-};
-
-// Same Rabbit as before
-function Rabbit(name) {
- this.name = name;
-}
-
-Rabbit.prototype.jump = function() {
- alert(this.name + ' jumps!');
-};
-
-*!*
-// setup the inheritance chain
-Rabbit.prototype.__proto__ = Animal.prototype; // (*)
-*/!*
-
-let rabbit = new Rabbit("White Rabbit");
-*!*
-rabbit.eat(); // rabbits can eat too
-*/!*
-rabbit.jump();
-```
-
-The line `(*)` sets up the prototype chain. So that `rabbit` first searches methods in `Rabbit.prototype`, then `Animal.prototype`. And then, just for completeness, let's mention that if the method is not found in `Animal.prototype`, then the search continues in `Object.prototype`, because `Animal.prototype` is a regular plain object, so it inherits from it.
-
-So here's the full picture:
-
-
-
-## Summary
-
-The term "class" comes from the object-oriented programming. In JavaScript it usually means the functional class pattern or the prototypal pattern. The prototypal pattern is more powerful and memory-efficient, so it's recommended to stick to it.
-
-According to the prototypal pattern:
-1. Methods are stored in `Class.prototype`.
-2. Prototypes inherit from each other.
-
-In the next chapter we'll study `class` keyword and construct. It allows to write prototypal classes shorter and provides some additional benefits.
diff --git a/1-js/07-object-oriented-programming/08-class-patterns/class-inheritance-rabbit-animal-2.png b/1-js/07-object-oriented-programming/08-class-patterns/class-inheritance-rabbit-animal-2.png
deleted file mode 100644
index ad4a409322..0000000000
Binary files a/1-js/07-object-oriented-programming/08-class-patterns/class-inheritance-rabbit-animal-2.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/08-class-patterns/class-inheritance-rabbit-animal-2@2x.png b/1-js/07-object-oriented-programming/08-class-patterns/class-inheritance-rabbit-animal-2@2x.png
deleted file mode 100644
index 199ed3ee60..0000000000
Binary files a/1-js/07-object-oriented-programming/08-class-patterns/class-inheritance-rabbit-animal-2@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/08-class-patterns/class-inheritance-rabbit-animal.png b/1-js/07-object-oriented-programming/08-class-patterns/class-inheritance-rabbit-animal.png
deleted file mode 100644
index 70708c2848..0000000000
Binary files a/1-js/07-object-oriented-programming/08-class-patterns/class-inheritance-rabbit-animal.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/08-class-patterns/class-inheritance-rabbit-animal@2x.png b/1-js/07-object-oriented-programming/08-class-patterns/class-inheritance-rabbit-animal@2x.png
deleted file mode 100644
index 0db1301815..0000000000
Binary files a/1-js/07-object-oriented-programming/08-class-patterns/class-inheritance-rabbit-animal@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/08-class-patterns/rabbit-animal-independent-1.png b/1-js/07-object-oriented-programming/08-class-patterns/rabbit-animal-independent-1.png
deleted file mode 100644
index 8df10f5d9a..0000000000
Binary files a/1-js/07-object-oriented-programming/08-class-patterns/rabbit-animal-independent-1.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/08-class-patterns/rabbit-animal-independent-1@2x.png b/1-js/07-object-oriented-programming/08-class-patterns/rabbit-animal-independent-1@2x.png
deleted file mode 100644
index b61ddfbd0b..0000000000
Binary files a/1-js/07-object-oriented-programming/08-class-patterns/rabbit-animal-independent-1@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/08-class-patterns/rabbit-animal-independent-2.png b/1-js/07-object-oriented-programming/08-class-patterns/rabbit-animal-independent-2.png
deleted file mode 100644
index 435ec5f89f..0000000000
Binary files a/1-js/07-object-oriented-programming/08-class-patterns/rabbit-animal-independent-2.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/08-class-patterns/rabbit-animal-independent-2@2x.png b/1-js/07-object-oriented-programming/08-class-patterns/rabbit-animal-independent-2@2x.png
deleted file mode 100644
index 5731da73a8..0000000000
Binary files a/1-js/07-object-oriented-programming/08-class-patterns/rabbit-animal-independent-2@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/09-class/1-rewrite-to-class/solution.view/clock.js b/1-js/07-object-oriented-programming/09-class/1-rewrite-to-class/solution.view/clock.js
deleted file mode 100644
index c710b9da9b..0000000000
--- a/1-js/07-object-oriented-programming/09-class/1-rewrite-to-class/solution.view/clock.js
+++ /dev/null
@@ -1,34 +0,0 @@
-class Clock {
- constructor({ template }) {
- this._template = template;
- }
-
- _render() {
- let date = new Date();
-
- let hours = date.getHours();
- if (hours < 10) hours = '0' + hours;
-
- let mins = date.getMinutes();
- if (mins < 10) min = '0' + mins;
-
- let secs = date.getSeconds();
- if (secs < 10) secs = '0' + secs;
-
- let output = this._template
- .replace('h', hours)
- .replace('m', mins)
- .replace('s', secs);
-
- console.log(output);
- }
-
- stop() {
- clearInterval(this._timer);
- }
-
- start() {
- this._render();
- this._timer = setInterval(() => this._render(), 1000);
- }
-}
diff --git a/1-js/07-object-oriented-programming/09-class/1-rewrite-to-class/solution.view/index.html b/1-js/07-object-oriented-programming/09-class/1-rewrite-to-class/solution.view/index.html
deleted file mode 100644
index fdee13d01b..0000000000
--- a/1-js/07-object-oriented-programming/09-class/1-rewrite-to-class/solution.view/index.html
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
- Console clock
-
-
-
-
-
-
-
-
-
-
diff --git a/1-js/07-object-oriented-programming/09-class/1-rewrite-to-class/source.view/clock.js b/1-js/07-object-oriented-programming/09-class/1-rewrite-to-class/source.view/clock.js
deleted file mode 100644
index b1a2625079..0000000000
--- a/1-js/07-object-oriented-programming/09-class/1-rewrite-to-class/source.view/clock.js
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-function Clock({ template }) {
- this._template = template;
-}
-
-Clock.prototype._render = function() {
- let date = new Date();
-
- let hours = date.getHours();
- if (hours < 10) hours = '0' + hours;
-
- let mins = date.getMinutes();
- if (mins < 10) min = '0' + mins;
-
- let secs = date.getSeconds();
- if (secs < 10) secs = '0' + secs;
-
- let output = this._template
- .replace('h', hours)
- .replace('m', mins)
- .replace('s', secs);
-
- console.log(output);
-};
-
-Clock.prototype.stop = function() {
- clearInterval(this._timer);
-};
-
-Clock.prototype.start = function() {
- this._render();
- this._timer = setInterval(() => this._render(), 1000);
-};
diff --git a/1-js/07-object-oriented-programming/09-class/1-rewrite-to-class/source.view/index.html b/1-js/07-object-oriented-programming/09-class/1-rewrite-to-class/source.view/index.html
deleted file mode 100644
index fdee13d01b..0000000000
--- a/1-js/07-object-oriented-programming/09-class/1-rewrite-to-class/source.view/index.html
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
- Console clock
-
-
-
-
-
-
-
-
-
-
diff --git a/1-js/07-object-oriented-programming/09-class/1-rewrite-to-class/task.md b/1-js/07-object-oriented-programming/09-class/1-rewrite-to-class/task.md
deleted file mode 100644
index a29d347f52..0000000000
--- a/1-js/07-object-oriented-programming/09-class/1-rewrite-to-class/task.md
+++ /dev/null
@@ -1,9 +0,0 @@
-importance: 5
-
----
-
-# Rewrite to class
-
-Rewrite the `Clock` class from prototypes to the modern "class" syntax.
-
-P.S. The clock ticks in the console, open it to see.
diff --git a/1-js/07-object-oriented-programming/09-class/animal-rabbit-extends.png b/1-js/07-object-oriented-programming/09-class/animal-rabbit-extends.png
deleted file mode 100644
index 2db88f3663..0000000000
Binary files a/1-js/07-object-oriented-programming/09-class/animal-rabbit-extends.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/09-class/animal-rabbit-extends@2x.png b/1-js/07-object-oriented-programming/09-class/animal-rabbit-extends@2x.png
deleted file mode 100644
index 9539fe9ec6..0000000000
Binary files a/1-js/07-object-oriented-programming/09-class/animal-rabbit-extends@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/09-class/article.md b/1-js/07-object-oriented-programming/09-class/article.md
deleted file mode 100644
index cb1beec085..0000000000
--- a/1-js/07-object-oriented-programming/09-class/article.md
+++ /dev/null
@@ -1,310 +0,0 @@
-
-# Classes
-
-The "class" construct allows to define prototype-based classes with a clean, nice-looking syntax.
-
-[cut]
-
-## The "class" syntax
-
-The `class` syntax is versatile, we'll start from a simple example first.
-
-Here's a prototype-based class `User`:
-
-```js run
-function User(name) {
- this.name = name;
-}
-
-User.prototype.sayHi = function() {
- alert(this.name);
-}
-
-let user = new User("John");
-user.sayHi();
-```
-
-...And that's the same using `class` syntax:
-
-```js run
-class User {
-
- constructor(name) {
- this.name = name;
- }
-
- sayHi() {
- alert(this.name);
- }
-
-}
-
-let user = new User("John");
-user.sayHi();
-```
-
-It's easy to see that the two examples are alike. So, what exactly does `class` do? We may think that it defines a new language-level entity, but that would be wrong.
-
-The `class User {...}` here actually does two things:
-
-1. Declares a variable `User` that references the function named `"constructor"`.
-2. Puts into `User.prototype` methods listed in the definition. Here it includes `sayHi` and the `constructor`.
-
-Here's some code to demonstrate that:
-
-```js run
-class User {
- constructor(name) { this.name = name; }
- sayHi() { alert(this.name); }
-}
-
-*!*
-// proof: User is the "constructor" function
-*/!*
-alert(User == User.prototype.constructor); // true
-
-*!*
-// proof: there are two methods in its "prototype"
-*/!*
-alert(Object.getOwnPropertyNames(User.prototype)); // constructor, sayHi
-```
-
-Here's the illustration of `class User`:
-
-
-
-So `class` is a special syntax to define the constructor with prototype methods.
-
-...But not only that. There are minor tweaks here and there to ensure the right usage.
-
-For instance, the `constructor` function can't be called without `new`:
-```js run
-class User {
- constructor() {}
-}
-
-alert(typeof User); // function
-User(); // Error: Class constructor User cannot be invoked without 'new'
-```
-
-```smart header="Outputting a class"
-If we output it like `alert(User)`, some engines show `"class User..."`, while others show `"function User..."`.
-
-Please don't be confused: the string representation may vary, but that's still a function, there is no separate "class" entity in JavaScript language.
-```
-
-```smart header="Class methods are non-enumerable"
-Class definition sets `enumerable` flag to `false` for all methods in the `"prototype"`. That's good, because if we `for..in` over an object, we usually don't want its class methods.
-```
-
-```smart header="What if there's no constructor?"
-If there's no `constructor` in the `class` construct, then an empty function is generated, same as if we had written `constructor() {}`.
-```
-
-```smart header="Classes always `use strict`"
-All code inside the class construct is automatically in strict mode.
-```
-
-### Getters/setters
-
-Classes may also include getters/setters. Here's an example with `user.name` implemented using them:
-
-```js run
-class User {
-
- constructor(name) {
- // invokes the setter
- this.name = name;
- }
-
-*!*
- get name() {
-*/!*
- return this._name;
- }
-
-*!*
- set name(value) {
-*/!*
- if (value.length < 4) {
- alert("Name too short.");
- return;
- }
- this._name = value;
- }
-
-}
-
-let user = new User("John");
-alert(user.name); // John
-
-user = new User(""); // Name too short.
-```
-
-### Only methods
-
-Unlike object literals, no `property:value` assignments are allowed inside `class`. There may be only methods (without a comma between them) and getters/setters.
-
-The idea is that everything inside `class` goes to the prototype. And the prototype should store methods only, which are shared between objects. The data describing a concrete object state should reside in individual objects.
-
-If we really insist on putting a non-function value into the prototype, then `class` can't help here. We can alter `prototype` manually though, like this:
-
-```js run
-class User { }
-
-User.prototype.test = 5;
-
-alert( new User().test ); // 5
-```
-
-So, technically that's possible, but we should know why we're doing it.
-
-An alternative here would be to use a getter:
-
-```js run
-class User {
- get test() {
- return 5;
- }
-}
-
-alert( new User().test ); // 5
-```
-
-From the external code, the usage is the same. But the getter variant is probably a bit slower.
-
-## Class Expression
-
-Just like functions, classes can be defined inside another expression, passed around, returned etc.
-
-Here's a class-returning function ("class factory"):
-
-```js run
-function getClass(phrase) {
-*!*
- return class {
- sayHi() {
- alert(phrase);
- };
- };
-*/!*
-}
-
-let User = getClass("Hello");
-
-new User().sayHi(); // Hello
-```
-
-That's quite normal if we recall that `class` is just a special form of function-with-prototype definition.
-
-And, like Named Function Expressions, such classes also may have a name, that is visible inside that class only:
-
-```js run
-let User = class *!*MyClass*/!* {
- sayHi() {
- alert(MyClass);
- }
-};
-
-new User().sayHi(); // works, shows MyClass definition
-
-alert(MyClass); // error, MyClass is only visible in methods of the class
-```
-
-## Static methods
-
-Static methods are bound to the class function, not to its `"prototype"`.
-
-An example:
-
-```js run
-class User {
-*!*
- static staticMethod() {
-*/!*
- alert(this == User);
- }
-}
-
-User.staticMethod(); // true
-```
-
-That actually does the same as assigning it as a function property:
-
-```js
-function User() { }
-
-User.staticMethod = function() {
- alert(this == User);
-};
-```
-
-The value of `this` inside `User.staticMethod()` is the class constructor `User` itself (the "object before dot" rule).
-
-Usually, static methods are used when the code is related to the class, but not to a particular object of it.
-
-For instance, we have `Article` objects and need a function to compare them. The natural choice would be `Article.compare`, like this:
-
-```js run
-class Article {
- constructor(title, date) {
- this.title = title;
- this.date = date;
- }
-
-*!*
- static compare(articleA, articleB) {
- return articleA.date - articleB.date;
- }
-*/!*
-}
-
-// usage
-let articles = [
- new Article("Mind", new Date(2016, 1, 1)),
- new Article("Body", new Date(2016, 0, 1)),
- new Article("JavaScript", new Date(2016, 11, 1))
-];
-
-*!*
-articles.sort(Article.compare);
-*/!*
-
-alert( articles[0].title ); // Body
-```
-
-Here `Article.compare` stands "over" the articles, as a means to compare them.
-
-Another example would be a so-called "factory" method, that creates an object with specific parameters.
-
-Like `Article.createTodays()` here:
-
-```js run
-class Article {
- constructor(title, date) {
- this.title = title;
- this.date = date;
- }
-
-*!*
- static createTodays() {
- // remember, this = Article
- return new this("Todays digest", new Date());
- }
-*/!*
-}
-
-let article = Article.createTodays();
-
-alert( articles.title ); // Todays digest
-```
-
-Now every time we need to create a todays digest, we can call `Article.createTodays()`.
-
-Static methods are often used in database-related classes to search/save/remove entries from the database, like this:
-
-```js
-// assuming Article is a special class for managing articles
-// static method to remove the article:
-Article.remove({id: 12345});
-```
diff --git a/1-js/07-object-oriented-programming/09-class/class-user.png b/1-js/07-object-oriented-programming/09-class/class-user.png
deleted file mode 100644
index 5579e6bbdf..0000000000
Binary files a/1-js/07-object-oriented-programming/09-class/class-user.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/09-class/class-user@2x.png b/1-js/07-object-oriented-programming/09-class/class-user@2x.png
deleted file mode 100644
index 5a85e6589d..0000000000
Binary files a/1-js/07-object-oriented-programming/09-class/class-user@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/10-class-inheritance/2-clock-class-extended/solution.view/clock.js b/1-js/07-object-oriented-programming/10-class-inheritance/2-clock-class-extended/solution.view/clock.js
deleted file mode 100644
index c710b9da9b..0000000000
--- a/1-js/07-object-oriented-programming/10-class-inheritance/2-clock-class-extended/solution.view/clock.js
+++ /dev/null
@@ -1,34 +0,0 @@
-class Clock {
- constructor({ template }) {
- this._template = template;
- }
-
- _render() {
- let date = new Date();
-
- let hours = date.getHours();
- if (hours < 10) hours = '0' + hours;
-
- let mins = date.getMinutes();
- if (mins < 10) min = '0' + mins;
-
- let secs = date.getSeconds();
- if (secs < 10) secs = '0' + secs;
-
- let output = this._template
- .replace('h', hours)
- .replace('m', mins)
- .replace('s', secs);
-
- console.log(output);
- }
-
- stop() {
- clearInterval(this._timer);
- }
-
- start() {
- this._render();
- this._timer = setInterval(() => this._render(), 1000);
- }
-}
diff --git a/1-js/07-object-oriented-programming/10-class-inheritance/2-clock-class-extended/solution.view/extended-clock.js b/1-js/07-object-oriented-programming/10-class-inheritance/2-clock-class-extended/solution.view/extended-clock.js
deleted file mode 100644
index 4eb12381f9..0000000000
--- a/1-js/07-object-oriented-programming/10-class-inheritance/2-clock-class-extended/solution.view/extended-clock.js
+++ /dev/null
@@ -1,12 +0,0 @@
-class ExtendedClock extends Clock {
- constructor(options) {
- super(options);
- let { precision=1000 } = options;
- this._precision = precision;
- }
-
- start() {
- this._render();
- this._timer = setInterval(() => this._render(), this._precision);
- }
-};
diff --git a/1-js/07-object-oriented-programming/10-class-inheritance/2-clock-class-extended/solution.view/index.html b/1-js/07-object-oriented-programming/10-class-inheritance/2-clock-class-extended/solution.view/index.html
deleted file mode 100644
index 7ac1db7143..0000000000
--- a/1-js/07-object-oriented-programming/10-class-inheritance/2-clock-class-extended/solution.view/index.html
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
- Console clock
-
-
-
-
-
-
-
-
-
-
-
diff --git a/1-js/07-object-oriented-programming/10-class-inheritance/2-clock-class-extended/source.view/clock.js b/1-js/07-object-oriented-programming/10-class-inheritance/2-clock-class-extended/source.view/clock.js
deleted file mode 100644
index c710b9da9b..0000000000
--- a/1-js/07-object-oriented-programming/10-class-inheritance/2-clock-class-extended/source.view/clock.js
+++ /dev/null
@@ -1,34 +0,0 @@
-class Clock {
- constructor({ template }) {
- this._template = template;
- }
-
- _render() {
- let date = new Date();
-
- let hours = date.getHours();
- if (hours < 10) hours = '0' + hours;
-
- let mins = date.getMinutes();
- if (mins < 10) min = '0' + mins;
-
- let secs = date.getSeconds();
- if (secs < 10) secs = '0' + secs;
-
- let output = this._template
- .replace('h', hours)
- .replace('m', mins)
- .replace('s', secs);
-
- console.log(output);
- }
-
- stop() {
- clearInterval(this._timer);
- }
-
- start() {
- this._render();
- this._timer = setInterval(() => this._render(), 1000);
- }
-}
diff --git a/1-js/07-object-oriented-programming/10-class-inheritance/2-clock-class-extended/source.view/index.html b/1-js/07-object-oriented-programming/10-class-inheritance/2-clock-class-extended/source.view/index.html
deleted file mode 100644
index b48a2a0074..0000000000
--- a/1-js/07-object-oriented-programming/10-class-inheritance/2-clock-class-extended/source.view/index.html
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
- Console clock
-
-
-
-
-
-
-
-
-
-
-
diff --git a/1-js/07-object-oriented-programming/10-class-inheritance/2-clock-class-extended/task.md b/1-js/07-object-oriented-programming/10-class-inheritance/2-clock-class-extended/task.md
deleted file mode 100644
index 05da453875..0000000000
--- a/1-js/07-object-oriented-programming/10-class-inheritance/2-clock-class-extended/task.md
+++ /dev/null
@@ -1,12 +0,0 @@
-importance: 5
-
----
-
-# Extended clock
-
-We've got a `Clock` class. As of now, it prints the time every second.
-
-Create a new class `ExtendedClock` that inherits from `Clock` and adds the parameter `precision` -- the number of `ms` between "ticks". Should be `1000` (1 second) by default.
-
-- Your code should be in the file `extended-clock.js`
-- Don't modify the original `clock.js`. Extend it.
diff --git a/1-js/07-object-oriented-programming/10-class-inheritance/3-class-extend-object/rabbit-extends-object.png b/1-js/07-object-oriented-programming/10-class-inheritance/3-class-extend-object/rabbit-extends-object.png
deleted file mode 100644
index d4ff37e561..0000000000
Binary files a/1-js/07-object-oriented-programming/10-class-inheritance/3-class-extend-object/rabbit-extends-object.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/10-class-inheritance/3-class-extend-object/rabbit-extends-object@2x.png b/1-js/07-object-oriented-programming/10-class-inheritance/3-class-extend-object/rabbit-extends-object@2x.png
deleted file mode 100644
index a54a9d2f86..0000000000
Binary files a/1-js/07-object-oriented-programming/10-class-inheritance/3-class-extend-object/rabbit-extends-object@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/10-class-inheritance/3-class-extend-object/solution.md b/1-js/07-object-oriented-programming/10-class-inheritance/3-class-extend-object/solution.md
deleted file mode 100644
index 16a20f2a6e..0000000000
--- a/1-js/07-object-oriented-programming/10-class-inheritance/3-class-extend-object/solution.md
+++ /dev/null
@@ -1,87 +0,0 @@
-The answer has two parts.
-
-The first, an easy one is that the inheriting class needs to call `super()` in the constructor. Otherwise `"this"` won't be "defined".
-
-So here's the fix:
-
-```js run
-class Rabbit extends Object {
- constructor(name) {
-*!*
- super(); // need to call the parent constructor when inheriting
-*/!*
- this.name = name;
- }
-}
-
-let rabbit = new Rabbit("Rab");
-
-alert( rabbit.hasOwnProperty('name') ); // true
-```
-
-But that's not all yet.
-
-Even after the fix, there's still important difference in `"class Rabbit extends Object"` versus `class Rabbit`.
-
-As we know, the "extends" syntax sets up two prototypes:
-
-1. Between `"prototype"` of the constructor functions (for methods).
-2. Between the constructor functions itself (for static methods).
-
-In our case, for `class Rabbit extends Object` it means:
-
-```js run
-class Rabbit extends Object {}
-
-alert( Rabbit.prototype.__proto__ === Object.prototype ); // (1) true
-alert( Rabbit.__proto__ === Object ); // (2) true
-```
-
-So we can access static methods of `Object` via `Rabbit`, like this:
-
-```js run
-class Rabbit extends Object {}
-
-*!*
-// normally we call Object.getOwnPropertyNames
-alert ( Rabbit.getOwnPropertyNames({a: 1, b: 2})); // a,b
-*/!*
-```
-
-And if we don't use `extends`, then `class Rabbit` does not get the second reference.
-
-Please compare with it:
-
-```js run
-class Rabbit {}
-
-alert( Rabbit.prototype.__proto__ === Object.prototype ); // (1) true
-alert( Rabbit.__proto__ === Object ); // (2) false (!)
-
-*!*
-// error, no such function in Rabbit
-alert ( Rabbit.getOwnPropertyNames({a: 1, b: 2})); // Error
-*/!*
-```
-
-For the simple `class Rabbit`, the `Rabbit` function has the same prototype
-
-```js run
-class Rabbit {}
-
-// instead of (2) that's correct for Rabbit (just like any function):
-alert( Rabbit.__proto__ === Function.prototype );
-```
-
-By the way, `Function.prototype` has "generic" function methods, like `call`, `bind` etc. They are ultimately available in both cases, because for the built-in `Object` constructor, `Object.__proto__ === Function.prototype`.
-
-Here's the picture:
-
-
-
-So, to put it short, there are two differences:
-
-| class Rabbit | class Rabbit extends Object |
-|--------------|------------------------------|
-| -- | needs to call `super()` in constructor |
-| `Rabbit.__proto__ === Function.prototype` | `Rabbit.__proto__ === Object` |
diff --git a/1-js/07-object-oriented-programming/10-class-inheritance/3-class-extend-object/task.md b/1-js/07-object-oriented-programming/10-class-inheritance/3-class-extend-object/task.md
deleted file mode 100644
index d59de085be..0000000000
--- a/1-js/07-object-oriented-programming/10-class-inheritance/3-class-extend-object/task.md
+++ /dev/null
@@ -1,43 +0,0 @@
-importance: 5
-
----
-
-# Class extends Object?
-
-As we know, all objects normally inherit from `Object.prototype` and get access to "generic" object methods.
-
-Like demonstrated here:
-
-```js run
-class Rabbit {
- constructor(name) {
- this.name = name;
- }
-}
-
-let rabbit = new Rabbit("Rab");
-
-*!*
-// hasOwnProperty method is from Object.prototype
-// rabbit.__proto__ === Object.prototype
-alert( rabbit.hasOwnProperty('name') ); // true
-*/!*
-```
-
-So, is it correct to say that `"class Rabbit extends Object"` does exactly the same as `"class Rabbit"`, or not?
-
-Will it work?
-
-```js
-class Rabbit extends Object {
- constructor(name) {
- this.name = name;
- }
-}
-
-let rabbit = new Rabbit("Rab");
-
-alert( rabbit.hasOwnProperty('name') ); // true
-```
-
-If it won't please fix the code.
diff --git a/1-js/07-object-oriented-programming/10-class-inheritance/animal-rabbit-static.png b/1-js/07-object-oriented-programming/10-class-inheritance/animal-rabbit-static.png
deleted file mode 100644
index 998c823300..0000000000
Binary files a/1-js/07-object-oriented-programming/10-class-inheritance/animal-rabbit-static.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/10-class-inheritance/animal-rabbit-static@2x.png b/1-js/07-object-oriented-programming/10-class-inheritance/animal-rabbit-static@2x.png
deleted file mode 100644
index 98a80d38fa..0000000000
Binary files a/1-js/07-object-oriented-programming/10-class-inheritance/animal-rabbit-static@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/10-class-inheritance/article.md b/1-js/07-object-oriented-programming/10-class-inheritance/article.md
deleted file mode 100644
index 1fe6687763..0000000000
--- a/1-js/07-object-oriented-programming/10-class-inheritance/article.md
+++ /dev/null
@@ -1,574 +0,0 @@
-
-# Class inheritance, super
-
-Classes can extend one another. There's a nice syntax, technically based on the prototypal inheritance.
-
-To inherit from another class, we should specify `"extends"` and the parent class before the brackets `{..}`.
-
-[cut]
-
-Here `Rabbit` inherits from `Animal`:
-
-```js run
-class Animal {
-
- constructor(name) {
- this.speed = 0;
- this.name = name;
- }
-
- run(speed) {
- this.speed += speed;
- alert(`${this.name} runs with speed ${this.speed}.`);
- }
-
- stop() {
- this.speed = 0;
- alert(`${this.name} stopped.`);
- }
-
-}
-
-*!*
-// Inherit from Animal
-class Rabbit extends Animal {
- hide() {
- alert(`${this.name} hides!`);
- }
-}
-*/!*
-
-let rabbit = new Rabbit("White Rabbit");
-
-rabbit.run(5); // White Rabbit runs with speed 5.
-rabbit.hide(); // White Rabbit hides!
-```
-
-The `extends` keyword actually adds a `[[Prototype]]` reference from `Rabbit.prototype` to `Animal.prototype`, just as you expect it to be, and as we've seen before.
-
-
-
-So now `rabbit` has access both to its own methods and to methods of `Animal`.
-
-````smart header="Any expression is allowed after `extends`"
-Class syntax allows to specify not just a class, but any expression after `extends`.
-
-For instance, a function call that generates the parent class:
-
-```js run
-function f(phrase) {
- return class {
- sayHi() { alert(phrase) }
- }
-}
-
-*!*
-class User extends f("Hello") {}
-*/!*
-
-new User().sayHi(); // Hello
-```
-Here `class User` inherits from the result of `f("Hello")`.
-
-That may be useful for advanced programming patterns when we use functions to generate classes depending on many conditions and can inherit from them.
-````
-
-## Overriding a method
-
-Now let's move forward and override a method. As of now, `Rabbit` inherits the `stop` method that sets `this.speed = 0` from `Animal`.
-
-If we specify our own `stop` in `Rabbit`, then it will be used instead:
-
-```js
-class Rabbit extends Animal {
- stop() {
- // ...this will be used for rabbit.stop()
- }
-}
-```
-
-
-...But usually we don't want to totally replace a parent method, but rather to build on top of it, tweak or extend its functionality. We do something in our method, but call the parent method before/after it or in the process.
-
-Classes provide `"super"` keyword for that.
-
-- `super.method(...)` to call a parent method.
-- `super(...)` to call a parent constructor (inside our constructor only).
-
-For instance, let our rabbit autohide when stopped:
-
-```js run
-class Animal {
-
- constructor(name) {
- this.speed = 0;
- this.name = name;
- }
-
- run(speed) {
- this.speed += speed;
- alert(`${this.name} runs with speed ${this.speed}.`);
- }
-
- stop() {
- this.speed = 0;
- alert(`${this.name} stopped.`);
- }
-
-}
-
-class Rabbit extends Animal {
- hide() {
- alert(`${this.name} hides!`);
- }
-
-*!*
- stop() {
- super.stop(); // call parent stop
- this.hide(); // and then hide
- }
-*/!*
-}
-
-let rabbit = new Rabbit("White Rabbit");
-
-rabbit.run(5); // White Rabbit runs with speed 5.
-rabbit.stop(); // White Rabbit stopped. White rabbit hides!
-```
-
-Now `Rabbit` has the `stop` method that calls the parent `super.stop()` in the process.
-
-````smart header="Arrow functions have no `super`"
-As was mentioned in the chapter , arrow functions do not have `super`.
-
-If accessed, it's taken from the outer function. For instance:
-```js
-class Rabbit extends Animal {
- stop() {
- setTimeout(() => super.stop(), 1000); // call parent stop after 1sec
- }
-}
-```
-
-The `super` in the arrow function is the same as in `stop()`, so it works as intended. If we specified a "regular" function here, there would be an error:
-
-```js
-// Unexpected super
-setTimeout(function() { super.stop() }, 1000);
-```
-````
-
-
-## Overriding constructor
-
-With constructors, things are is a little bit tricky.
-
-Till now, `Rabbit` did not have its own `constructor`.
-
-According to the [specification](https://tc39.github.io/ecma262/#sec-runtime-semantics-classdefinitionevaluation), if a class extends another class and has no `constructor`, then the following `constructor` is generated:
-
-```js
-class Rabbit extends Animal {
- // generated for extending classes without own constructors
-*!*
- constructor(...args) {
- super(...args);
- }
-*/!*
-}
-```
-
-As we can see, it basically calls the parent `constructor` passing it all the arguments. That happens if we don't write a constructor of our own.
-
-Now let's add a custom constructor to `Rabbit`. It will specify the `earLength` in addition to `name`:
-
-```js run
-class Animal {
- constructor(name) {
- this.speed = 0;
- this.name = name;
- }
- // ...
-}
-
-class Rabbit extends Animal {
-
-*!*
- constructor(name, earLength) {
- this.speed = 0;
- this.name = name;
- this.earLength = earLength;
- }
-*/!*
-
- // ...
-}
-
-*!*
-// Doesn't work!
-let rabbit = new Rabbit("White Rabbit", 10); // Error: this is not defined.
-*/!*
-```
-
-Whoops! We've got an error. Now we can't create rabbits. What went wrong?
-
-The short answer is: constructors in inheriting classes must call `super(...)`, and (!) do it before using `this`.
-
-...But why? What's going on here? Indeed, the requirement seems strange.
-
-Of course, there's an explanation. Let's get into details, so you'd really understand what's going on.
-
-In JavaScript, there's a distinction between a "constructor function of an inheriting class" and all others. In an inheriting class, the corresponding constructor function is labelled with a special internal property `[[ConstructorKind]]:"derived"`.
-
-The difference is:
-
-- When a normal constructor runs, it creates an empty object as `this` and continues with it.
-- But when a derived constructor runs, it doesn't do it. It expects the parent constructor to do this job.
-
-So if we're making a constructor of our own, then we must call `super`, because otherwise the object with `this` reference to it won't be created. And we'll get an error.
-
-For `Rabbit` to work, we need to call `super()` before using `this`, like here:
-
-```js run
-class Animal {
-
- constructor(name) {
- this.speed = 0;
- this.name = name;
- }
-
- // ...
-}
-
-class Rabbit extends Animal {
-
- constructor(name, earLength) {
-*!*
- super(name);
-*/!*
- this.earLength = earLength;
- }
-
- // ...
-}
-
-*!*
-// now fine
-let rabbit = new Rabbit("White Rabbit", 10);
-alert(rabbit.name); // White Rabbit
-alert(rabbit.earLength); // 10
-*/!*
-```
-
-
-## Super: internals, [[HomeObject]]
-
-Let's get a little deeper under the hood of `super`. We'll see some interesting things by the way.
-
-First to say, from all that we've learned till now, it's impossible for `super` to work.
-
-Yeah, indeed, let's ask ourselves, how it could technically work? When an object method runs, it gets the current object as `this`. If we call `super.method()` then, how to retrieve that method? In other words, we need to take the `method` from the parent prototype of the current object. How, technically, we (or a JavaScript engine) can do it?
-
-Maybe we can get it `[[Prototype]]` of `this`, as `this.__proto__.method`? Unfortunately, that won't work.
-
-Let's try to do it. Without classes, using plain objects for the sake of simplicity.
-
-Here, `rabbit.eat()` should call `animal.eat()` method of the parent object:
-
-```js run
-let animal = {
- name: "Animal",
- eat() {
- alert(this.name + " eats.");
- }
-};
-
-let rabbit = {
- __proto__: animal,
- name: "Rabbit",
- eat() {
-*!*
- this.__proto__.eat.call(this); // (*)
-*/!*
- }
-};
-
-rabbit.eat(); // Rabbit eats.
-```
-
-At the line `(*)` we take `eat` from the prototype (`animal`) and call it in the context of the current object. Please note that `.call(this)` is important here, because a simple `this.__proto__.eat()` would execute parent `eat` in the context of the prototype, not the current object.
-
-And here it works.
-
-Now let's add one more object to the chain. We'll see how things break:
-
-```js run
-let animal = {
- name: "Animal",
- eat() {
- alert(this.name + " eats.");
- }
-};
-
-let rabbit = {
- __proto__: animal,
- eat() {
- // ...bounce around rabbit-style and call parent (animal) method
- this.__proto__.eat.call(this); // (*)
- }
-};
-
-let longEar = {
- __proto__: rabbit,
- eat() {
- // ...do something with long ears and call parent (rabbit) method
- this.__proto__.eat.call(this); // (**)
- }
-};
-
-*!*
-longEar.eat(); // Error: Maximum call stack size exceeded
-*/!*
-```
-
-The code doesn't work any more! We can see the error trying to call `longEar.eat()`.
-
-It may be not that obvious, but if we trace `longEar.eat()` call, then we can see why. In both lines `(*)` and `(**)` the value of `this` is the current object (`longEar`). That's essential: all object methods get the current object as `this`, not a prototype or something.
-
-So, in both lines `(*)` and `(**)` the value of `this.__proto__` is exactly the same: `rabbit`. They both call `rabbit.eat` without going up the chain.
-
-In other words:
-
-1. Inside `longEar.eat()`, we pass the call up to `rabbit.eat` giving it the same `this=longEar`.
- ```js
- // inside longEar.eat() we have this = longEar
- this.__proto__.eat.call(this) // (**)
- // becomes
- longEar.__proto__.eat.call(this)
- // or
- rabbit.eat.call(this);
- ```
-2. Inside `rabbit.eat`, we want to pass the call even higher in the chain, but `this=longEar`, so `this.__proto__.eat` is `rabbit.eat`!
-
- ```js
- // inside rabbit.eat() we also have this = longEar
- this.__proto__.eat.call(this) // (*)
- // becomes
- longEar.__proto__.eat.call(this)
- // or (again)
- rabbit.eat.call(this);
- ```
-
-3. ...So `rabbit.eat` calls itself in the endless loop, because it can't ascend any further.
-
-
-
-There problem is unsolvable, because `this` must always be the calling object itself, no matter which parent method is called. So its prototype will always be the immediate parent of the object. We can't go up the chain.
-
-### `[[HomeObject]]`
-
-To provide the solution, JavaScript adds one more special internal property for functions: `[[HomeObject]]`.
-
-**When a function is specified as a class or object method, its `[[HomeObject]]` property becomes that object.**
-
-This actually violates the idea of "unbound" functions, because methods remember their objects. And `[[HomeObject]]` can't be changed, so this bound is forever. So that's a very important change in the language.
-
-But this change is safe. `[[HomeObject]]` is used only for calling parent methods in `super`, to resolve the prototype. So it doesn't break compatibility.
-
-Let's see how it works for `super` -- again, using plain objects:
-
-```js run
-let animal = {
- name: "Animal",
- eat() { // [[HomeObject]] == animal
- alert(this.name + " eats.");
- }
-};
-
-let rabbit = {
- __proto__: animal,
- name: "Rabbit",
- eat() { // [[HomeObject]] == rabbit
- super.eat();
- }
-};
-
-let longEar = {
- __proto__: rabbit,
- name: "Long Ear",
- eat() { // [[HomeObject]] == longEar
- super.eat();
- }
-};
-
-*!*
-longEar.eat(); // Long Ear eats.
-*/!*
-```
-
-Every method remembers its object in the internal `[[HomeObject]]` property. Then `super` uses it to resolve the parent prototype.
-
-`[[HomeObject]]` is defined for methods defined both in classes and in plain objects. But for objects, methods must be specified exactly the given way: as `method()`, not as `"method: function()"`.
-
-In the example below a non-method syntax is used for comparison. `[[HomeObject]]` property is not set and the inheritance doesn't work:
-
-```js run
-let animal = {
- eat: function() { // should be the short syntax: eat() {...}
- // ...
- }
-};
-
-let rabbit = {
- __proto__: animal,
- eat: function() {
- super.eat();
- }
-};
-
-*!*
-rabbit.eat(); // Error calling super (because there's no [[HomeObject]])
-*/!*
-```
-
-## Static methods and inheritance
-
-The `class` syntax supports inheritance for static properties too.
-
-For instance:
-
-```js run
-class Animal {
-
- constructor(name, speed) {
- this.speed = speed;
- this.name = name;
- }
-
- run(speed = 0) {
- this.speed += speed;
- alert(`${this.name} runs with speed ${this.speed}.`);
- }
-
- static compare(animalA, animalB) {
- return animalA.speed - animalB.speed;
- }
-
-}
-
-// Inherit from Animal
-class Rabbit extends Animal {
- hide() {
- alert(`${this.name} hides!`);
- }
-}
-
-let rabbits = [
- new Rabbit("White Rabbit", 10),
- new Rabbit("Black Rabbit", 5)
-];
-
-rabbits.sort(Rabbit.compare);
-
-rabbits[0].run(); // Black Rabbit runs with speed 5.
-```
-
-Now we can call `Rabbit.compare` assuming that the inherited `Animal.compare` will be called.
-
-How does it work? Again, using prototypes. As you might have already guessed, extends also gives `Rabbit` the `[[Prototype]]` reference to `Animal`.
-
-
-
-
-So, `Rabbit` function now inherits from `Animal` function. And `Animal` function normally has `[[Prototype]]` referencing `Function.prototype`, because it doesn't `extend` anything.
-
-Here, let's check that:
-
-```js run
-class Animal {}
-class Rabbit extends Animal {}
-
-// for static propertites and methods
-alert(Rabbit.__proto__ == Animal); // true
-
-// and the next step is Function.prototype
-alert(Animal.__proto__ == Function.prototype); // true
-
-// that's in addition to the "normal" prototype chain for object methods
-alert(Rabbit.prototype.__proto__ === Animal.prototype);
-```
-
-This way `Rabbit` has access to all static methods of `Animal`.
-
-Please note that built-in classes don't have such static `[[Prototype]]` reference. For instance, `Object` has `Object.defineProperty`, `Object.keys` and so on, but `Array`, `Date` etc do not inherit them.
-
-Here's the picture structure for `Date` and `Object`:
-
-
-
-Note, there's no link between `Date` and `Object`. Both `Object` and `Date` exist independently. `Date.prototype` inherits from `Object.prototype`, but that's all.
-
-Such difference exists for historical reasons: there was no thought about class syntax and inheriting static methods at the dawn of JavaScript language.
-
-## Natives are extendable
-
-Built-in classes like Array, Map and others are extendable also.
-
-For instance, here `PowerArray` inherits from the native `Array`:
-
-```js run
-// add one more method to it (can do more)
-class PowerArray extends Array {
- isEmpty() {
- return this.length == 0;
- }
-}
-
-let arr = new PowerArray(1, 2, 5, 10, 50);
-alert(arr.isEmpty()); // false
-
-let filteredArr = arr.filter(item => item >= 10);
-alert(filteredArr); // 10, 50
-alert(filteredArr.isEmpty()); // false
-```
-
-Please note one very interesting thing. Built-in methods like `filter`, `map` and others -- return new objects of exactly the inherited type. They rely on the `constructor` property to do so.
-
-In the example above,
-```js
-arr.constructor === PowerArray
-```
-
-So when `arr.filter()` is called, it internally creates the new array of results exactly as `new PowerArray`. And we can keep using its methods further down the chain.
-
-Even more, we can customize that behavior. The static getter `Symbol.species`, if exists, returns the constructor to use in such cases.
-
-For example, here due to `Symbol.species` built-in methods like `map`, `filter` will return "normal" arrays:
-
-```js run
-class PowerArray extends Array {
- isEmpty() {
- return this.length == 0;
- }
-
-*!*
- // built-in methods will use this as the constructor
- static get [Symbol.species]() {
- return Array;
- }
-*/!*
-}
-
-let arr = new PowerArray(1, 2, 5, 10, 50);
-alert(arr.isEmpty()); // false
-
-// filter creates new array using arr.constructor[Symbol.species] as constructor
-let filteredArr = arr.filter(item => item >= 10);
-
-*!*
-// filteredArr is not PowerArray, but Array
-*/!*
-alert(filteredArr.isEmpty()); // Error: filteredArr.isEmpty is not a function
-```
-
-We can use it in more advanced keys to strip extended functionality from resulting values if not needed. Or, maybe, to extend it even further.
diff --git a/1-js/07-object-oriented-programming/10-class-inheritance/class-inheritance-array-object.png b/1-js/07-object-oriented-programming/10-class-inheritance/class-inheritance-array-object.png
deleted file mode 100644
index c5d712632f..0000000000
Binary files a/1-js/07-object-oriented-programming/10-class-inheritance/class-inheritance-array-object.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/10-class-inheritance/class-inheritance-array-object@2x.png b/1-js/07-object-oriented-programming/10-class-inheritance/class-inheritance-array-object@2x.png
deleted file mode 100644
index edc4e841ec..0000000000
Binary files a/1-js/07-object-oriented-programming/10-class-inheritance/class-inheritance-array-object@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/10-class-inheritance/class-inheritance-rabbit-animal.png b/1-js/07-object-oriented-programming/10-class-inheritance/class-inheritance-rabbit-animal.png
deleted file mode 100644
index 70708c2848..0000000000
Binary files a/1-js/07-object-oriented-programming/10-class-inheritance/class-inheritance-rabbit-animal.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/10-class-inheritance/class-inheritance-rabbit-animal@2x.png b/1-js/07-object-oriented-programming/10-class-inheritance/class-inheritance-rabbit-animal@2x.png
deleted file mode 100644
index 0db1301815..0000000000
Binary files a/1-js/07-object-oriented-programming/10-class-inheritance/class-inheritance-rabbit-animal@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/10-class-inheritance/class-inheritance-rabbit-run-animal.png b/1-js/07-object-oriented-programming/10-class-inheritance/class-inheritance-rabbit-run-animal.png
deleted file mode 100644
index 387975a9c7..0000000000
Binary files a/1-js/07-object-oriented-programming/10-class-inheritance/class-inheritance-rabbit-run-animal.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/10-class-inheritance/class-inheritance-rabbit-run-animal@2x.png b/1-js/07-object-oriented-programming/10-class-inheritance/class-inheritance-rabbit-run-animal@2x.png
deleted file mode 100644
index ca73135933..0000000000
Binary files a/1-js/07-object-oriented-programming/10-class-inheritance/class-inheritance-rabbit-run-animal@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/10-class-inheritance/object-date-inheritance.png b/1-js/07-object-oriented-programming/10-class-inheritance/object-date-inheritance.png
deleted file mode 100644
index 542a0c9fa9..0000000000
Binary files a/1-js/07-object-oriented-programming/10-class-inheritance/object-date-inheritance.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/10-class-inheritance/object-date-inheritance@2x.png b/1-js/07-object-oriented-programming/10-class-inheritance/object-date-inheritance@2x.png
deleted file mode 100644
index 21485062a8..0000000000
Binary files a/1-js/07-object-oriented-programming/10-class-inheritance/object-date-inheritance@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/10-class-inheritance/this-super-loop.png b/1-js/07-object-oriented-programming/10-class-inheritance/this-super-loop.png
deleted file mode 100644
index bb4c1fc439..0000000000
Binary files a/1-js/07-object-oriented-programming/10-class-inheritance/this-super-loop.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/10-class-inheritance/this-super-loop@2x.png b/1-js/07-object-oriented-programming/10-class-inheritance/this-super-loop@2x.png
deleted file mode 100644
index 91d2e03cb9..0000000000
Binary files a/1-js/07-object-oriented-programming/10-class-inheritance/this-super-loop@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/11-instanceof/1-strange-instanceof/task.md b/1-js/07-object-oriented-programming/11-instanceof/1-strange-instanceof/task.md
deleted file mode 100644
index e9481912ae..0000000000
--- a/1-js/07-object-oriented-programming/11-instanceof/1-strange-instanceof/task.md
+++ /dev/null
@@ -1,20 +0,0 @@
-importance: 5
-
----
-
-# Strange instanceof
-
-Why `instanceof` below returns `true`? We can easily see that `a` is not created by `B()`.
-
-```js run
-function A() {}
-function B() {}
-
-A.prototype = B.prototype = {};
-
-let a = new A();
-
-*!*
-alert( a instanceof B ); // true
-*/!*
-```
diff --git a/1-js/07-object-oriented-programming/11-instanceof/article.md b/1-js/07-object-oriented-programming/11-instanceof/article.md
deleted file mode 100644
index 1d725eea88..0000000000
--- a/1-js/07-object-oriented-programming/11-instanceof/article.md
+++ /dev/null
@@ -1,213 +0,0 @@
-# Class checking: "instanceof"
-
-The `instanceof` operator allows to check whether an object belongs to a certain class. It also takes inheritance into account.
-
-Such a check may be necessary in many cases, here we'll use it for building a *polymorphic* function, the one that treats arguments differently depending on their type.
-
-[cut]
-
-## The instanceof operator [#ref-instanceof]
-
-The syntax is:
-```js
-obj instanceof Class
-```
-
-It returns `true` if `obj` belongs to the `Class` (or a class inheriting from it).
-
-For instance:
-
-```js run
-class Rabbit {}
-let rabbit = new Rabbit();
-
-// is it an object of Rabbit class?
-*!*
-alert( rabbit instanceof Rabbit ); // true
-*/!*
-```
-
-It also works with constructor functions:
-
-```js run
-*!*
-// instead of class
-function Rabbit() {}
-*/!*
-
-alert( new Rabbit() instanceof Rabbit ); // true
-```
-
-...And with built-in classes like `Array`:
-
-```js run
-let arr = [1, 2, 3];
-alert( arr instanceof Array ); // true
-alert( arr instanceof Object ); // true
-```
-
-Please note that `arr` also belongs to the `Object` class. That's because `Array` prototypally inherits from `Object`.
-
-The `instanceof` operator examines the prototype chain for the check, and is also fine-tunable using the static method `Symbol.hasInstance`.
-
-The algorithm of `obj instanceof Class` works roughly as follows:
-
-1. If there's a static method `Symbol.hasInstance`, then use it. Like this:
-
- ```js run
- // assume anything that canEat is an animal
- class Animal {
- static [Symbol.hasInstance](obj) {
- if (obj.canEat) return true;
- }
- }
-
- let obj = { canEat: true };
- alert(obj instanceof Animal); // true: Animal[Symbol.hasInstance](obj) is called
- ```
-
-2. Most classes do not have `Symbol.hasInstance`. In that case, check if `Class.prototype` equals to one of prototypes in the `obj` prototype chain.
-
- In other words, compare:
- ```js
- obj.__proto__ == Class.prototype
- obj.__proto__.__proto__ == Class.prototype
- obj.__proto__.__proto__.__proto__ == Class.prototype
- ...
- ```
-
- In the example above `Rabbit.prototype == rabbit.__proto__`, so that gives the answer immediately.
-
- In the case of an inheritance, `rabbit` is an instance of the parent class as well:
-
- ```js run
- class Animal {}
- class Rabbit extends Animal {}
-
- let rabbit = new Rabbit();
- *!*
- alert(rabbit instanceof Animal); // true
- */!*
- // rabbit.__proto__ == Rabbit.prototype
- // rabbit.__proto__.__proto__ == Animal.prototype (match!)
- ```
-
-Here's the illustration of what `rabbit instanceof Animal` compares with `Animal.prototype`:
-
-
-
-By the way, there's also a method [objA.isPrototypeOf(objB)](mdn:js/object/isPrototypeOf), that returns `true` if `objA` is somewhere in the chain of prototypes for `objB`. So the test of `obj instanceof Class` can be rephrased as `Class.prototype.isPrototypeOf(obj)`.
-
-That's funny, but the `Class` constructor itself does not participate in the check! Only the chain of prototypes and `Class.prototype` matters.
-
-That can lead to interesting consequences when `prototype` is changed.
-
-Like here:
-
-```js run
-function Rabbit() {}
-let rabbit = new Rabbit();
-
-// changed the prototype
-Rabbit.prototype = {};
-
-// ...not a rabbit any more!
-*!*
-alert( rabbit instanceof Rabbit ); // false
-*/!*
-```
-
-That's one of reasons to avoid changing `prototype`. Just to keep safe.
-
-## Bonus: Object toString for the type
-
-We already know that plain objects are converted to string as `[object Object]`:
-
-```js run
-let obj = {};
-
-alert(obj); // [object Object]
-alert(obj.toString()); // the same
-```
-
-That's their implementation of `toString`. But there's a hidden feature thank makes `toString` actually much more powerful than that. We can use it as an extended `typeof` and an alternative for `instanceof`.
-
-Sounds strange? Indeed. Let's demistify.
-
-By [specification](https://tc39.github.io/ecma262/#sec-object.prototype.tostring), the built-in `toString` can be extracted from the object and executed in the context of any other value. And its result depends on that value.
-
-- For a number, it will be `[object Number]`
-- For a boolean, it will be `[object Boolean]`
-- For `null`: `[object Null]`
-- For `undefined`: `[object Undefined]`
-- For arrays: `[object Array]`
-- ...etc (customizable).
-
-Let's demonstrate:
-
-```js run
-// copy toString method into a variable for convenience
-let objectToString = Object.prototype.toString;
-
-// what type is this?
-let arr = [];
-
-alert( objectToString.call(arr) ); // [object Array]
-```
-
-Here we used [call](mdn:js/function/call) as described in the chapter [](info:call-apply-decorators) to execute the function `objectToString` in the context `this=arr`.
-
-Internally, the `toString` algorithm examines `this` and returns the corresponding result. More examples:
-
-```js run
-let s = Object.prototype.toString;
-
-alert( s.call(123) ); // [object Number]
-alert( s.call(null) ); // [object Null]
-alert( s.call(alert) ); // [object Function]
-```
-
-### Symbol.toStringTag
-
-The behavior of Object `toString` can be customized using a special object property `Symbol.toStringTag`.
-
-For instance:
-
-```js run
-let user = {
- [Symbol.toStringTag]: 'User'
-};
-
-alert( {}.toString.call(user) ); // [object User]
-```
-
-For most environment-specific objects, there is such a property. Here are few browser specific examples:
-
-```js run
-// toStringTag for the envinronment-specific object and class:
-alert( window[Symbol.toStringTag]); // window
-alert( XMLHttpRequest.prototype[Symbol.toStringTag] ); // XMLHttpRequest
-
-alert( {}.toString.call(window) ); // [object Window]
-alert( {}.toString.call(new XMLHttpRequest()) ); // [object XMLHttpRequest]
-```
-
-As you can see, the result is exactly `Symbol.toStringTag` (if exists), wrapped into `[object ...]`.
-
-At the end we have "typeof on steroids" that not only works for primitive data types, but also for built-in objects and even can be customized.
-
-It can be used instead of `instanceof` for built-in objects when we want to get the type as a string rather than just to check.
-
-## Summary
-
-Let's recap the type-checking methods that we know:
-
-| | works for | returns |
-|---------------|-------------|---------------|
-| `typeof` | primitives | string |
-| `{}.toString` | primitives, built-in objects, objects with `Symbol.toStringTag` | string |
-| `instanceof` | objects | true/false |
-
-As we can see, `{}.toString` is technically a "more advanced" `typeof`.
-
-And `instanceof` operator really shines when we are working with a class hierarchy and want to check for the class taking into account inheritance.
diff --git a/1-js/07-object-oriented-programming/11-instanceof/instanceof.png b/1-js/07-object-oriented-programming/11-instanceof/instanceof.png
deleted file mode 100644
index 85aa9a55f3..0000000000
Binary files a/1-js/07-object-oriented-programming/11-instanceof/instanceof.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/11-instanceof/instanceof@2x.png b/1-js/07-object-oriented-programming/11-instanceof/instanceof@2x.png
deleted file mode 100644
index fba7712207..0000000000
Binary files a/1-js/07-object-oriented-programming/11-instanceof/instanceof@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/13-mixins/article.md b/1-js/07-object-oriented-programming/13-mixins/article.md
deleted file mode 100644
index 624f442677..0000000000
--- a/1-js/07-object-oriented-programming/13-mixins/article.md
+++ /dev/null
@@ -1,199 +0,0 @@
-# Mixins
-
-In JavaScript we can only inherit from a single object. There can be only one `[[Prototype]]`.
-
-But sometimes we need such kind of thing. For instance, we have a code that implements events exchange or templating, and we'd like to be able to add these capabilities to any class easily.
-
-What can help here is *mixins*.
-
-As [defined in Wikipedia](https://en.wikipedia.org/wiki/Mixin), a *mixin* is a class that contains methods for use by other classes without having to be the parent class of those other classes.
-
-In other words, a *mixin* is a class that implements a certain behavior. But we do not use it alone, we use it to add the behavior to other classes.
-
-## A mixin example
-
-The simplest way to make a mixin in JavaScript -- is to make an object with useful methods, that we can just copy into the prototype.
-
-For instance here the mixin `sayHiMixin` is used to add some "speech" for `User`:
-
-```js run
-*!*
-// mixin
-*/!*
-let sayHiMixin = {
- sayHi() {
- alert("Hello " + this.name);
- },
- sayBye() {
- alert("Bye " + this.name);
- }
-};
-
-*!*
-// usage:
-*/!*
-class User {
- constructor(name) {
- this.name = name;
- }
-}
-
-// copy the methods
-Object.assign(User.prototype, sayHiMixin);
-
-// now User can say hi
-new User("Dude").sayHi(); // Hi Dude!
-```
-
-There's no inheritance, there's a simple method copying. So `User` may extend some other class and also include the mixin to "mix-in" the additional methods.
-
-Mixins also can make use of inheritance.
-
-For instance, here `sayHiMixin` inherits from `sayMixin`:
-
-```js run
-let sayMixin = {
- say(phrase) {
- alert(phrase);
- }
-};
-
-let sayHiMixin = {
- // can use any way of prototype setting here
- __proto__: sayMixin,
-
- sayHi() {
- *!*
- // call parent method
- */!*
- super.say("Hello " + this.name);
- },
- sayBye() {
- super.say("Bye " + this.name);
- }
-};
-
-class User {
- constructor(name) {
- this.name = name;
- }
-}
-
-// copy the methods
-Object.assign(User.prototype, sayHiMixin);
-
-// now User can say hi
-new User("Dude").sayHi(); // Hi Dude!
-```
-
-Please note that the call to the parent method `super.say()` from `sayHiMixin` looks for the method in the prototype of that mixin, not the class.
-
-
-
-That's because methods from `sayHiMixin` have `[[HomeObject]]` set to it. So `super` actually means `sayHiMixin.__proto__`, not `User.__proto__`.
-
-## EventMixin
-
-Now a mixin for the real life.
-
-The important feature of many objects is working with events.
-
-That is: an object should have a method to "generate an event" when something important happens to it, and other objects should be able to "subscribe" to receive such notifications.
-
-An event must have a name and, if necessary, the attached data.
-
-For instance, an object `user` can generate an event `"login"` when the visitor logs in. And an object `calendar` may want to receive such notifications and load the information about that visitor.
-
-Or, the object `menu` can generate the event `"select"` when a menu item is selected, and other objects may want to get that information and react on that event.
-
-Events is a way to "share information" with anyone who wants it.
-
-Here is `eventMixin` that implements the corresponding methods:
-
-```js run
-let eventMixin = {
-
- /**
- * Subscribe to event, usage:
- * menu.on('select', function(item) { ... }
- */
- on(eventName, handler) {
- if (!this._eventHandlers) this._eventHandlers = {};
- if (!this._eventHandlers[eventName]) {
- this._eventHandlers[eventName] = [];
- }
- this._eventHandlers[eventName].push(handler);
- },
-
- /**
- * Cancel the subscription, usage:
- * menu.off('select', handler)
- */
- off(eventName, handler) {
- let handlers = this._eventHandlers && this._eventHandlers[eventName];
- if (!handlers) return;
- for(let i = 0; i < handlers.length; i++) {
- if (handlers[i] == handler) {
- handlers.splice(i--, 1);
- }
- }
- },
-
- /**
- * Generate the event and attach the data to it
- * this.trigger('select', data1, data2);
- */
- trigger(eventName, ...args) {
- if (!this._eventHandlers || !this._eventHandlers[eventName]) {
- return; // no handlers for that event name
- }
-
- // call the handlers
- this._eventHandlers[eventName].forEach(handler => handler.apply(this, args));
- }
-};
-```
-
-There are 3 methods here:
-
-1. `.on(eventName, handler)` -- assigns function `handler` to run when the event with that name happens. The handlers are stored in the `_eventHandlers` property.
-2. `.off(eventName, handler)` -- removes the function from the handlers list.
-3. `.trigger(eventName, ...args)` -- generates the event: all assigned handlers are called and `args` are passed as arguments to them.
-
-
-Usage:
-
-```js run
-// Make a class
-class Menu {
- choose(value) {
- this.trigger("select", value);
- }
-}
-// Add the mixin
-Object.assign(Menu.prototype, eventMixin);
-
-let menu = new Menu();
-
-// call the handler on selection:
-*!*
-menu.on("select", value => alert("Value selected: " + value));
-*/!*
-
-// triggers the event => shows Value selected: 123
-menu.choose("123"); // value selected
-```
-
-Now if we have the code interested to react on user selection, we can bind it with `menu.on(...)`.
-
-And the `eventMixin` can add such behavior to as many classes as we'd like, without interfering with the inheritance chain.
-
-## Summary
-
-*Mixin* -- is a generic object-oriented programming term: a class that contains methods for other classes.
-
-Some other languages like e.g. python allow to create mixins using multiple inheritance. JavaScript does not support multiple inheritance, but mixins can be implemented by copying them into the prototype.
-
-We can use mixins as a way to augment a class by multiple behaviors, like event-handling as we have seen above.
-
-Mixins may become a point of conflict if they occasionally overwrite native class methods. So generally one should think well about the naming for a mixin, to minimize such possibility.
diff --git a/1-js/07-object-oriented-programming/13-mixins/head.html b/1-js/07-object-oriented-programming/13-mixins/head.html
deleted file mode 100644
index 77ea38b204..0000000000
--- a/1-js/07-object-oriented-programming/13-mixins/head.html
+++ /dev/null
@@ -1,43 +0,0 @@
-
diff --git a/1-js/07-object-oriented-programming/13-mixins/mixin-inheritance.png b/1-js/07-object-oriented-programming/13-mixins/mixin-inheritance.png
deleted file mode 100644
index 7cc655036f..0000000000
Binary files a/1-js/07-object-oriented-programming/13-mixins/mixin-inheritance.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/13-mixins/mixin-inheritance@2x.png b/1-js/07-object-oriented-programming/13-mixins/mixin-inheritance@2x.png
deleted file mode 100644
index f53ecf68fd..0000000000
Binary files a/1-js/07-object-oriented-programming/13-mixins/mixin-inheritance@2x.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/index.md b/1-js/07-object-oriented-programming/index.md
deleted file mode 100644
index 7053ada816..0000000000
--- a/1-js/07-object-oriented-programming/index.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Objects, classes, inheritance
-
-In this section we return to objects and learn them even more in-depth.
diff --git a/1-js/07-object-properties/01-property-descriptors/article.md b/1-js/07-object-properties/01-property-descriptors/article.md
new file mode 100644
index 0000000000..0a945b377b
--- /dev/null
+++ b/1-js/07-object-properties/01-property-descriptors/article.md
@@ -0,0 +1,349 @@
+
+# Property flags and descriptors
+
+As we know, objects can store properties.
+
+Until now, a property was a simple "key-value" pair to us. But an object property is actually a more flexible and powerful thing.
+
+In this chapter we'll study additional configuration options, and in the next we'll see how to invisibly turn them into getter/setter functions.
+
+## Property flags
+
+Object properties, besides a **`value`**, have three special attributes (so-called "flags"):
+
+- **`writable`** -- if `true`, the value can be changed, otherwise it's read-only.
+- **`enumerable`** -- if `true`, then listed in loops, otherwise not listed.
+- **`configurable`** -- if `true`, the property can be deleted and these attributes can be modified, otherwise not.
+
+We didn't see them yet, because generally they do not show up. When we create a property "the usual way", all of them are `true`. But we also can change them anytime.
+
+First, let's see how to get those flags.
+
+The method [Object.getOwnPropertyDescriptor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptor) allows to query the *full* information about a property.
+
+The syntax is:
+```js
+let descriptor = Object.getOwnPropertyDescriptor(obj, propertyName);
+```
+
+`obj`
+: The object to get information from.
+
+`propertyName`
+: The name of the property.
+
+The returned value is a so-called "property descriptor" object: it contains the value and all the flags.
+
+For instance:
+
+```js run
+let user = {
+ name: "John"
+};
+
+let descriptor = Object.getOwnPropertyDescriptor(user, 'name');
+
+alert( JSON.stringify(descriptor, null, 2 ) );
+/* property descriptor:
+{
+ "value": "John",
+ "writable": true,
+ "enumerable": true,
+ "configurable": true
+}
+*/
+```
+
+To change the flags, we can use [Object.defineProperty](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty).
+
+The syntax is:
+
+```js
+Object.defineProperty(obj, propertyName, descriptor)
+```
+
+`obj`, `propertyName`
+: The object and its property to apply the descriptor.
+
+`descriptor`
+: Property descriptor object to apply.
+
+If the property exists, `defineProperty` updates its flags. Otherwise, it creates the property with the given value and flags; in that case, if a flag is not supplied, it is assumed `false`.
+
+For instance, here a property `name` is created with all falsy flags:
+
+```js run
+let user = {};
+
+*!*
+Object.defineProperty(user, "name", {
+ value: "John"
+});
+*/!*
+
+let descriptor = Object.getOwnPropertyDescriptor(user, 'name');
+
+alert( JSON.stringify(descriptor, null, 2 ) );
+/*
+{
+ "value": "John",
+*!*
+ "writable": false,
+ "enumerable": false,
+ "configurable": false
+*/!*
+}
+ */
+```
+
+Compare it with "normally created" `user.name` above: now all flags are falsy. If that's not what we want then we'd better set them to `true` in `descriptor`.
+
+Now let's see effects of the flags by example.
+
+## Non-writable
+
+Let's make `user.name` non-writable (can't be reassigned) by changing `writable` flag:
+
+```js run
+let user = {
+ name: "John"
+};
+
+Object.defineProperty(user, "name", {
+*!*
+ writable: false
+*/!*
+});
+
+*!*
+user.name = "Pete"; // Error: Cannot assign to read only property 'name'
+*/!*
+```
+
+Now no one can change the name of our user, unless they apply their own `defineProperty` to override ours.
+
+```smart header="Errors appear only in strict mode"
+In non-strict mode, no errors occur when writing to non-writable properties and such. But the operation still won't succeed. Flag-violating actions are just silently ignored in non-strict.
+```
+
+Here's the same example, but the property is created from scratch:
+
+```js run
+let user = { };
+
+Object.defineProperty(user, "name", {
+*!*
+ value: "John",
+ // for new properties we need to explicitly list what's true
+ enumerable: true,
+ configurable: true
+*/!*
+});
+
+alert(user.name); // John
+user.name = "Pete"; // Error
+```
+
+## Non-enumerable
+
+Now let's add a custom `toString` to `user`.
+
+Normally, a built-in `toString` for objects is non-enumerable, it does not show up in `for..in`. But if we add a `toString` of our own, then by default it shows up in `for..in`, like this:
+
+```js run
+let user = {
+ name: "John",
+ toString() {
+ return this.name;
+ }
+};
+
+// By default, both our properties are listed:
+for (let key in user) alert(key); // name, toString
+```
+
+If we don't like it, then we can set `enumerable:false`. Then it won't appear in a `for..in` loop, just like the built-in one:
+
+```js run
+let user = {
+ name: "John",
+ toString() {
+ return this.name;
+ }
+};
+
+Object.defineProperty(user, "toString", {
+*!*
+ enumerable: false
+*/!*
+});
+
+*!*
+// Now our toString disappears:
+*/!*
+for (let key in user) alert(key); // name
+```
+
+Non-enumerable properties are also excluded from `Object.keys`:
+
+```js
+alert(Object.keys(user)); // name
+```
+
+## Non-configurable
+
+The non-configurable flag (`configurable:false`) is sometimes preset for built-in objects and properties.
+
+A non-configurable property can't be deleted, its attributes can't be modified.
+
+For instance, `Math.PI` is non-writable, non-enumerable and non-configurable:
+
+```js run
+let descriptor = Object.getOwnPropertyDescriptor(Math, 'PI');
+
+alert( JSON.stringify(descriptor, null, 2 ) );
+/*
+{
+ "value": 3.141592653589793,
+ "writable": false,
+ "enumerable": false,
+ "configurable": false
+}
+*/
+```
+So, a programmer is unable to change the value of `Math.PI` or overwrite it.
+
+```js run
+Math.PI = 3; // Error, because it has writable: false
+
+// delete Math.PI won't work either
+```
+
+We also can't change `Math.PI` to be `writable` again:
+
+```js run
+// Error, because of configurable: false
+Object.defineProperty(Math, "PI", { writable: true });
+```
+
+There's absolutely nothing we can do with `Math.PI`.
+
+Making a property non-configurable is a one-way road. We cannot change it back with `defineProperty`.
+
+**Please note: `configurable: false` prevents changes of property flags and its deletion, while allowing to change its value.**
+
+Here `user.name` is non-configurable, but we can still change it (as it's writable):
+
+```js run
+let user = {
+ name: "John"
+};
+
+Object.defineProperty(user, "name", {
+ configurable: false
+});
+
+user.name = "Pete"; // works fine
+delete user.name; // Error
+```
+
+And here we make `user.name` a "forever sealed" constant, just like the built-in `Math.PI`:
+
+```js run
+let user = {
+ name: "John"
+};
+
+Object.defineProperty(user, "name", {
+ writable: false,
+ configurable: false
+});
+
+// won't be able to change user.name or its flags
+// all this won't work:
+user.name = "Pete";
+delete user.name;
+Object.defineProperty(user, "name", { value: "Pete" });
+```
+
+```smart header="The only attribute change possible: writable true -> false"
+There's a minor exception about changing flags.
+
+We can change `writable: true` to `false` for a non-configurable property, thus preventing its value modification (to add another layer of protection). Not the other way around though.
+```
+
+## Object.defineProperties
+
+There's a method [Object.defineProperties(obj, descriptors)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperties) that allows to define many properties at once.
+
+The syntax is:
+
+```js
+Object.defineProperties(obj, {
+ prop1: descriptor1,
+ prop2: descriptor2
+ // ...
+});
+```
+
+For instance:
+
+```js
+Object.defineProperties(user, {
+ name: { value: "John", writable: false },
+ surname: { value: "Smith", writable: false },
+ // ...
+});
+```
+
+So, we can set many properties at once.
+
+## Object.getOwnPropertyDescriptors
+
+To get all property descriptors at once, we can use the method [Object.getOwnPropertyDescriptors(obj)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptors).
+
+Together with `Object.defineProperties` it can be used as a "flags-aware" way of cloning an object:
+
+```js
+let clone = Object.defineProperties({}, Object.getOwnPropertyDescriptors(obj));
+```
+
+Normally when we clone an object, we use an assignment to copy properties, like this:
+
+```js
+for (let key in user) {
+ clone[key] = user[key]
+}
+```
+
+...But that does not copy flags. So if we want a "better" clone then `Object.defineProperties` is preferred.
+
+Another difference is that `for..in` ignores symbolic and non-enumerable properties, but `Object.getOwnPropertyDescriptors` returns *all* property descriptors including symbolic and non-enumerable ones.
+
+## Sealing an object globally
+
+Property descriptors work at the level of individual properties.
+
+There are also methods that limit access to the *whole* object:
+
+[Object.preventExtensions(obj)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/preventExtensions)
+: Forbids the addition of new properties to the object.
+
+[Object.seal(obj)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/seal)
+: Forbids adding/removing of properties. Sets `configurable: false` for all existing properties.
+
+[Object.freeze(obj)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze)
+: Forbids adding/removing/changing of properties. Sets `configurable: false, writable: false` for all existing properties.
+
+And also there are tests for them:
+
+[Object.isExtensible(obj)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible)
+: Returns `false` if adding properties is forbidden, otherwise `true`.
+
+[Object.isSealed(obj)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isSealed)
+: Returns `true` if adding/removing properties is forbidden, and all existing properties have `configurable: false`.
+
+[Object.isFrozen(obj)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isFrozen)
+: Returns `true` if adding/removing/changing properties is forbidden, and all current properties are `configurable: false, writable: false`.
+
+These methods are rarely used in practice.
diff --git a/1-js/07-object-properties/02-property-accessors/article.md b/1-js/07-object-properties/02-property-accessors/article.md
new file mode 100644
index 0000000000..c2aa35d53a
--- /dev/null
+++ b/1-js/07-object-properties/02-property-accessors/article.md
@@ -0,0 +1,244 @@
+
+# Property getters and setters
+
+There are two kinds of object properties.
+
+The first kind is *data properties*. We already know how to work with them. All properties that we've been using until now were data properties.
+
+The second type of property is something new. It's an *accessor property*. They are essentially functions that execute on getting and setting a value, but look like regular properties to an external code.
+
+## Getters and setters
+
+Accessor properties are represented by "getter" and "setter" methods. In an object literal they are denoted by `get` and `set`:
+
+```js
+let obj = {
+ *!*get propName()*/!* {
+ // getter, the code executed on getting obj.propName
+ },
+
+ *!*set propName(value)*/!* {
+ // setter, the code executed on setting obj.propName = value
+ }
+};
+```
+
+The getter works when `obj.propName` is read, the setter -- when it is assigned.
+
+For instance, we have a `user` object with `name` and `surname`:
+
+```js
+let user = {
+ name: "John",
+ surname: "Smith"
+};
+```
+
+Now we want to add a `fullName` property, that should be `"John Smith"`. Of course, we don't want to copy-paste existing information, so we can implement it as an accessor:
+
+```js run
+let user = {
+ name: "John",
+ surname: "Smith",
+
+*!*
+ get fullName() {
+ return `${this.name} ${this.surname}`;
+ }
+*/!*
+};
+
+*!*
+alert(user.fullName); // John Smith
+*/!*
+```
+
+From the outside, an accessor property looks like a regular one. That's the idea of accessor properties. We don't *call* `user.fullName` as a function, we *read* it normally: the getter runs behind the scenes.
+
+As of now, `fullName` has only a getter. If we attempt to assign `user.fullName=`, there will be an error:
+
+```js run
+let user = {
+ get fullName() {
+ return `...`;
+ }
+};
+
+*!*
+user.fullName = "Test"; // Error (property has only a getter)
+*/!*
+```
+
+Let's fix it by adding a setter for `user.fullName`:
+
+```js run
+let user = {
+ name: "John",
+ surname: "Smith",
+
+ get fullName() {
+ return `${this.name} ${this.surname}`;
+ },
+
+*!*
+ set fullName(value) {
+ [this.name, this.surname] = value.split(" ");
+ }
+*/!*
+};
+
+// set fullName is executed with the given value.
+user.fullName = "Alice Cooper";
+
+alert(user.name); // Alice
+alert(user.surname); // Cooper
+```
+
+As the result, we have a "virtual" property `fullName`. It is readable and writable.
+
+## Accessor descriptors
+
+Descriptors for accessor properties are different from those for data properties.
+
+For accessor properties, there is no `value` or `writable`, but instead there are `get` and `set` functions.
+
+That is, an accessor descriptor may have:
+
+- **`get`** -- a function without arguments, that works when a property is read,
+- **`set`** -- a function with one argument, that is called when the property is set,
+- **`enumerable`** -- same as for data properties,
+- **`configurable`** -- same as for data properties.
+
+For instance, to create an accessor `fullName` with `defineProperty`, we can pass a descriptor with `get` and `set`:
+
+```js run
+let user = {
+ name: "John",
+ surname: "Smith"
+};
+
+*!*
+Object.defineProperty(user, 'fullName', {
+ get() {
+ return `${this.name} ${this.surname}`;
+ },
+
+ set(value) {
+ [this.name, this.surname] = value.split(" ");
+ }
+*/!*
+});
+
+alert(user.fullName); // John Smith
+
+for(let key in user) alert(key); // name, surname
+```
+
+Please note that a property can be either an accessor (has `get/set` methods) or a data property (has a `value`), not both.
+
+If we try to supply both `get` and `value` in the same descriptor, there will be an error:
+
+```js run
+*!*
+// Error: Invalid property descriptor.
+*/!*
+Object.defineProperty({}, 'prop', {
+ get() {
+ return 1
+ },
+
+ value: 2
+});
+```
+
+## Smarter getters/setters
+
+Getters/setters can be used as wrappers over "real" property values to gain more control over operations with them.
+
+For instance, if we want to forbid too short names for `user`, we can have a setter `name` and keep the value in a separate property `_name`:
+
+```js run
+let user = {
+ get name() {
+ return this._name;
+ },
+
+ set name(value) {
+ if (value.length < 4) {
+ alert("Name is too short, need at least 4 characters");
+ return;
+ }
+ this._name = value;
+ }
+};
+
+user.name = "Pete";
+alert(user.name); // Pete
+
+user.name = ""; // Name is too short...
+```
+
+So, the name is stored in `_name` property, and the access is done via getter and setter.
+
+Technically, external code is able to access the name directly by using `user._name`. But there is a widely known convention that properties starting with an underscore `"_"` are internal and should not be touched from outside the object.
+
+
+## Using for compatibility
+
+One of the great uses of accessors is that they allow to take control over a "regular" data property at any moment by replacing it with a getter and a setter and tweak its behavior.
+
+Imagine we started implementing user objects using data properties `name` and `age`:
+
+```js
+function User(name, age) {
+ this.name = name;
+ this.age = age;
+}
+
+let john = new User("John", 25);
+
+alert( john.age ); // 25
+```
+
+...But sooner or later, things may change. Instead of `age` we may decide to store `birthday`, because it's more precise and convenient:
+
+```js
+function User(name, birthday) {
+ this.name = name;
+ this.birthday = birthday;
+}
+
+let john = new User("John", new Date(1992, 6, 1));
+```
+
+Now what to do with the old code that still uses `age` property?
+
+We can try to find all such places and fix them, but that takes time and can be hard to do if that code is used by many other people. And besides, `age` is a nice thing to have in `user`, right?
+
+Let's keep it.
+
+Adding a getter for `age` solves the problem:
+
+```js run no-beautify
+function User(name, birthday) {
+ this.name = name;
+ this.birthday = birthday;
+
+*!*
+ // age is calculated from the current date and birthday
+ Object.defineProperty(this, "age", {
+ get() {
+ let todayYear = new Date().getFullYear();
+ return todayYear - this.birthday.getFullYear();
+ }
+ });
+*/!*
+}
+
+let john = new User("John", new Date(1992, 6, 1));
+
+alert( john.birthday ); // birthday is available
+alert( john.age ); // ...as well as the age
+```
+
+Now the old code works too and we've got a nice additional property.
diff --git a/1-js/07-object-properties/index.md b/1-js/07-object-properties/index.md
new file mode 100644
index 0000000000..67fcccaffc
--- /dev/null
+++ b/1-js/07-object-properties/index.md
@@ -0,0 +1,3 @@
+# Object properties configuration
+
+In this section we return to objects and study their properties even more in-depth.
diff --git a/1-js/08-error-handling/1-try-catch/1-finally-or-code-after/solution.md b/1-js/08-error-handling/1-try-catch/1-finally-or-code-after/solution.md
deleted file mode 100644
index 05ba72e008..0000000000
--- a/1-js/08-error-handling/1-try-catch/1-finally-or-code-after/solution.md
+++ /dev/null
@@ -1,47 +0,0 @@
-The difference becomes obvious when we look at the code inside a function.
-
-The behavior is different if there's a "jump out" of `try..catch`.
-
-For instance, when there's a `return` inside `try..catch`. The `finally` clause works in case of *any* exit from `try..catch`, even via the `return` statement: right after `try..catch` is done, but before the calling code gets the control.
-
-```js run
-function f() {
- try {
- alert('start');
-*!*
- return "result";
-*/!*
- } catch (e) {
- /// ...
- } finally {
- alert('cleanup!');
- }
-}
-
-f(); // cleanup!
-```
-
-...Or when there's a `throw`, like here:
-
-```js run
-function f() {
- try {
- alert('start');
- throw new Error("an error");
- } catch (e) {
- // ...
- if("can't handle the error") {
-*!*
- throw e;
-*/!*
- }
-
- } finally {
- alert('cleanup!')
- }
-}
-
-f(); // cleanup!
-```
-
-It's `finally` that guarantees the cleanup here. If we just put the code at the end of `f`, it wouldn't run.
diff --git a/1-js/08-error-handling/1-try-catch/1-finally-or-code-after/task.md b/1-js/08-error-handling/1-try-catch/1-finally-or-code-after/task.md
deleted file mode 100644
index e846873438..0000000000
--- a/1-js/08-error-handling/1-try-catch/1-finally-or-code-after/task.md
+++ /dev/null
@@ -1,38 +0,0 @@
-importance: 5
-
----
-
-# Finally or just the code?
-
-Compare the two code fragments.
-
-1. The first one uses `finally` to execute the code after `try..catch`:
-
- ```js
- try {
- work work
- } catch (e) {
- handle errors
- } finally {
- *!*
- cleanup the working space
- */!*
- }
- ```
-2. The second fragment puts the cleaning right after `try..catch`:
-
- ```js
- try {
- work work
- } catch (e) {
- handle errors
- }
-
- *!*
- cleanup the working space
- */!*
- ```
-
-We definitely need the cleanup after the work has started, doesn't matter if there was an error or not.
-
-Is there an advantage here in using `finally` or both code fragments are equal? If there is such an advantage, then give an example when it matters.
diff --git a/1-js/08-error-handling/1-try-catch/article.md b/1-js/08-error-handling/1-try-catch/article.md
deleted file mode 100644
index bc3b509bd8..0000000000
--- a/1-js/08-error-handling/1-try-catch/article.md
+++ /dev/null
@@ -1,662 +0,0 @@
-# Error handling, "try..catch"
-
-No matter how great we are at programming, sometimes our scripts have errors. They may occur because of our mistakes, an unexpected user input, an erroneous server response and for a thousand of other reasons.
-
-Usually, a script "dies" (immediately stops) in case of an error, printing it to console.
-
-But there's a syntax construct `try..catch` that allows to "catch" errors and, instead of dying, do something more reasonable.
-
-[cut]
-
-## The "try..catch" syntax
-
-The `try..catch` construct has two main blocks: `try`, and then `catch`:
-
-```js
-try {
-
- // code...
-
-} catch (err) {
-
- // error handling
-
-}
-```
-
-It works like this:
-
-1. First, the code in `try {...}` is executed.
-2. If there were no errors, then `catch(err)` is ignored: the execution reaches the end of `try` and then jumps over `catch`.
-3. If an error occurs, then `try` execution is stopped, and the control flows to the beginning of `catch(err)`. The `err` variable (can use any name for it) contains an error object with details about what's happened.
-
-
-
-So, an error inside the `try {…}` block does not kill the script: we have a chance to handle it in `catch`.
-
-Let's see more examples.
-
-- An errorless example: shows `alert` `(1)` and `(2)`:
-
- ```js run
- try {
-
- alert('Start of try runs'); // *!*(1) <--*/!*
-
- // ...no errors here
-
- alert('End of try runs'); // *!*(2) <--*/!*
-
- } catch(err) {
-
- alert('Catch is ignored, because there are no errors'); // (3)
-
- }
-
- alert("...Then the execution continues");
- ```
-- An example with an error: shows `(1)` and `(3)`:
-
- ```js run
- try {
-
- alert('Start of try runs'); // *!*(1) <--*/!*
-
- *!*
- lalala; // error, variable is not defined!
- */!*
-
- alert('End of try (never reached)'); // (2)
-
- } catch(err) {
-
- alert(`Error has occured!`); // *!*(3) <--*/!*
-
- }
-
- alert("...Then the execution continues");
- ```
-
-
-````warn header="`try..catch` only works for runtime errors"
-For `try..catch` to work, the code must be runnable. In other words, it should be valid JavaScript.
-
-It won't work if the code is syntactically wrong, for instance it has unmatched figure brackets:
-
-```js run
-try {
- {{{{{{{{{{{{
-} catch(e) {
- alert("The engine can't understand this code, it's invalid");
-}
-```
-
-The JavaScript engine first reads the code, and then runs it. The errors that occur on the reading phrase are called "parse-time" errors and are unrecoverable (from inside that code). That's because the engine can't understand the code.
-
-So, `try..catch` can only handle errors that occur in the valid code. Such errors are called "runtime errors" or, sometimes, "exceptions".
-````
-
-
-````warn header="`try..catch` works synchronously"
-If an exception happens in a "scheduled" code, like in `setTimeout`, then `try..catch` won't catch it:
-
-```js run
-try {
- setTimeout(function() {
- noSuchVariable; // script will die here
- }, 1000);
-} catch (e) {
- alert( "won't work" );
-}
-```
-
-That's because `try..catch` actually wraps the `setTimeout` call that schedules the function. But the function itself is executed later, when the engine has already have left the `try..catch` construct.
-
-To catch an exception inside a scheduled function, `try..catch` must be inside that function:
-```js run
-setTimeout(function() {
- try {
- noSuchVariable; // try..catch handles the error!
- } catch (e) {
- alert( "error is caught here!" );
- }
-}, 1000);
-```
-````
-
-## Error object
-
-When an error occurs, JavaScript generates an object containing the details about it. The object is then passed as an argument to `catch`:
-
-```js
-try {
- // ...
-} catch(err) { // <-- the "error object", could use another word instead of err
- // ...
-}
-```
-
-For all built-in errors, the error object inside `catch` block has two main properties:
-
-`name`
-: Error name. For an undefined variable that's `"ReferenceError"`.
-
-`message`
-: Textual message about error details.
-
-There are other non-standard properties available in most environments. One of most widely used and supported is:
-
-`stack`
-: Current call stack: a string with information about the sequence of nested calls that led to the error. Used for debugging purposes.
-
-For instance:
-
-```js run untrusted
-try {
-*!*
- lalala; // error, variable is not defined!
-*/!*
-} catch(err) {
- alert(err.name); // ReferenceError
- alert(err.message); // lalala is not defined
- alert(err.stack); // ReferenceError: lalala is not defined at ...
-
- // Can also show an error as a whole
- // The error is converted to string as "name: message"
- alert(err); // ReferenceError: lalala is not defined
-}
-```
-
-
-## Using "try..catch"
-
-Let's explore a real-life use case of `try..catch`.
-
-As we already know, JavaScript supports method [JSON.parse(str)](mdn:js/JSON/parse) to read JSON-encoded values.
-
-Usually it's used to decode the data received over the network, from the server or another source.
-
-We receive it and call `JSON.parse`, like this:
-
-```js run
-let json = '{"name":"John", "age": 30}'; // data from the server
-
-*!*
-let user = JSON.parse(json); // convert the text representation to JS object
-*/!*
-
-// now user is an object with properties from the string
-alert( user.name ); // John
-alert( user.age ); // 30
-```
-
-More detailed information about JSON you can find in the chapter .
-
-**If `json` is malformed, `JSON.parse` generates an error, so the script "dies".**
-
-Should we be satisfied with that? Of course, not!
-
-This way if something's wrong with the data, the visitor will never know that (unless he opens developer console). And people really really don't like when something "just dies" without any error message.
-
-Let's use `try..catch` to handle the error:
-
-```js run
-let json = "{ bad json }";
-
-try {
-
-*!*
- let user = JSON.parse(json); // <-- when an error occurs...
-*/!*
- alert( user.name ); // doesn't work
-
-} catch (e) {
-*!*
- // ...the execution jumps here
- alert( "Our apologies, the data has errors, we'll try to request it one more time." );
- alert( e.name );
- alert( e.message );
-*/!*
-}
-```
-
-Here we use `catch` block only to show the message, but we can do much more: a new network request, suggest an alternative to the visitor, send the information about the error to a logging facility... All much better than just dying.
-
-## Throwing our own errors
-
-What if `json` is syntactically correct... But doesn't have a required `"name"` property?
-
-Like this:
-
-```js run
-let json = '{ "age": 30 }'; // incomplete data
-
-try {
-
- let user = JSON.parse(json); // <-- no errors
-*!*
- alert( user.name ); // no name!
-*/!*
-
-} catch (e) {
- alert( "doesn't execute" );
-}
-```
-
-Here `JSON.parse` runs normally, but the absence of `"name"` is actually an error for us.
-
-To unify error handling, we'll use the `throw` operator.
-
-### "Throw" operator
-
-The `throw` operator generates an error.
-
-The syntax is:
-
-```js
-throw
-```
-
-Technically, we can use anything as an error object. That may be even a primitive, like a number or a string, but it's better to use objects, preferrably with `name` and `message` properties (to stay somewhat compatible with built-in errors).
-
-JavaScript has many built-in constructors for standard errors: `Error`, `SyntaxError`, `ReferenceError`, `TypeError` and others. We can use them to create error objects as well.
-
-Their syntax is:
-
-```js
-let error = new Error(message);
-// or
-let error = new SyntaxError(message);
-let error = new ReferenceError(message);
-// ...
-```
-
-For built-in errors (not for any objects, just for errors), the `name` property is exactly the name of the constructor. And `message` is taken from the argument.
-
-For instance:
-
-```js run
-let error = new Error("Things happen o_O");
-
-alert(error.name); // Error
-alert(error.message); // Things happen o_O
-```
-
-Let's see what kind of error `JSON.parse` generates:
-
-```js run
-try {
- JSON.parse("{ bad json o_O }");
-} catch(e) {
-*!*
- alert(e.name); // SyntaxError
-*/!*
- alert(e.message); // Unexpected token o in JSON at position 0
-}
-```
-
-As we can see, that's a `SyntaxError`.
-
-...And in our case, the absense of `name` could be treated as a syntax error also, assuming that users must have a `"name"`.
-
-So let's throw it:
-
-```js run
-let json = '{ "age": 30 }'; // incomplete data
-
-try {
-
- let user = JSON.parse(json); // <-- no errors
-
- if (!user.name) {
-*!*
- throw new SyntaxError("Incomplete data: no name"); // (*)
-*/!*
- }
-
- alert( user.name );
-
-} catch(e) {
- alert( "JSON Error: " + e.message ); // JSON Error: Incomplete data: no name
-}
-```
-
-In the line `(*)` the `throw` operator generates `SyntaxError` with the given `message`, the same way as JavaScript would generate itself. The execution of `try` immediately stops and the control flow jumps into `catch`.
-
-Now `catch` became a single place for all error handling: both for `JSON.parse` and other cases.
-
-## Rethrowing
-
-In the example above we use `try..catch` to handle incorrect data. But is it possible that *another unexpected error* occurs within the `try {...}` block? Like a variable is undefined or something else, not just that "incorrect data" thing.
-
-Like this:
-
-```js run
-let json = '{ "age": 30 }'; // incomplete data
-
-try {
- user = JSON.parse(json); // <-- forgot to put "let" before user
-
- // ...
-} catch(err) {
- alert("JSON Error: " + err); // JSON Error: ReferenceError: user is not defined
- // (not JSON Error actually)
-}
-```
-
-Of course, everything's possible! Programmers do make mistakes. Even in open-source utilities used by millions for decades -- suddenly a crazy bug may be discovered that leads to terrible hacks (like it happened with the `ssh` tool).
-
-In our case, `try..catch` is meant to catch "incorrect data" errors. But by its nature, `catch` gets *all* errors from `try`. Here it gets an unexpected error, but still shows the same `"JSON Error"` message. That's wrong and also makes the code more difficult to debug.
-
-Fortunately, we can find out which error we get, for instance from its `name`:
-
-```js run
-try {
- user = { /*...*/ };
-} catch(e) {
-*!*
- alert(e.name); // "ReferenceError" for accessing an undefined variable
-*/!*
-}
-```
-
-The rule is simple:
-
-**Catch should only process errors that it knows and "rethrow" all others.**
-
-The "rethrowing" technique can be explained in more detail as:
-
-1. Catch gets all errors.
-2. In `catch(err) {...}` block we analyze the error object `err`.
-2. If we don't know how to handle it, then we do `throw err`.
-
-In the code below, we use rethrowing so that `catch` only handles `SyntaxError`:
-
-```js run
-let json = '{ "age": 30 }'; // incomplete data
-try {
-
- let user = JSON.parse(json);
-
- if (!user.name) {
- throw new SyntaxError("Incomplete data: no name");
- }
-
-*!*
- blabla(); // unexpected error
-*/!*
-
- alert( user.name );
-
-} catch(e) {
-
-*!*
- if (e.name == "SyntaxError") {
- alert( "JSON Error: " + e.message );
- } else {
- throw e; // rethrow (*)
- }
-*/!*
-
-}
-```
-
-The error throwing on line `(*)` from inside `catch` block "falls out" of `try..catch` and can be either caught by an outer `try..catch` construct (if it exists), or it kills the script.
-
-So the `catch` block actually handles only errors that it knows how to deal with and "skips" all others.
-
-The example below demonstrates how such errors can be caught by one more level of `try..catch`:
-
-```js run
-function readData() {
- let json = '{ "age": 30 }';
-
- try {
- // ...
-*!*
- blabla(); // error!
-*/!*
- } catch (e) {
- // ...
- if (e.name != 'SyntaxError') {
-*!*
- throw e; // rethrow (don't know how to deal with it)
-*/!*
- }
- }
-}
-
-try {
- readData();
-} catch (e) {
-*!*
- alert( "External catch got: " + e ); // caught it!
-*/!*
-}
-```
-
-Here `readData` only knows how to handle `SyntaxError`, while the outer `try..catch` knows how to handle everything.
-
-## try..catch..finally
-
-Wait, that's not all.
-
-The `try..catch` construct may have one more code clause: `finally`.
-
-If it exists, it runs in all cases:
-
-- after `try`, if there were no errors,
-- after `catch`, if there were errors.
-
-The extended syntax looks like this:
-
-```js
-*!*try*/!* {
- ... try to execute the code ...
-} *!*catch*/!*(e) {
- ... handle errors ...
-} *!*finally*/!* {
- ... execute always ...
-}
-```
-
-Try running this code:
-
-```js run
-try {
- alert( 'try' );
- if (confirm('Make an error?')) BAD_CODE();
-} catch (e) {
- alert( 'catch' );
-} finally {
- alert( 'finally' );
-}
-```
-
-The code has two ways of execution:
-
-1. If you answer "Yes" to "Make an error?", then `try -> catch -> finally`.
-2. If you say "No", then `try -> finally`.
-
-The `finally` clause is often used when we start doing something before `try..catch` and want to finalize it in any case of outcome.
-
-For instance, we want to measure time that a Fibonacci numbers function `fib(n)` takes. Naturally, we can start measuring before it runs and finish afterwards. But what if there's an error during the function call? In particular, the implementation of `fib(n)` in the code below returns an error for negative or non-integer numbers.
-
-The `finally` clause is a great place to finish the measurements no matter what.
-
-Here `finally` guarantees that the time will be measured correctly in both situations -- in case of a successful execution of `fib` and in case of an error in it:
-
-```js run
-let num = +prompt("Enter a positive integer number?", 35)
-
-let diff, result;
-
-function fib(n) {
- if (n < 0 || Math.trunc(n) != n) {
- throw new Error("Must not be negative, and also an integer.");
- }
- return n <= 1 ? n : fib(n - 1) + fib(n - 2);
-}
-
-let start = Date.now();
-
-try {
- result = fib(num);
-} catch (e) {
- result = 0;
-*!*
-} finally {
- diff = Date.now() - start;
-}
-*/!*
-
-alert(result || "error occured");
-
-alert( `execution took ${diff}ms` );
-```
-
-You can check by running the code with entering `35` into `prompt` -- it executes normally, `finally` after `try`. And then enter `-1` -- there will be an immediate error, an the execution will take `0ms`. Both measurements are done correctly.
-
-In other words, there may be two ways to exit a function: either a `return` or `throw`. The `finally` clause handles them both.
-
-
-```smart header="Variables are local inside `try..catch..finally`"
-Please note that `result` and `diff` variables in the code above are declared *before* `try..catch`.
-
-Otherwise, if `let` were made inside the `{...}` block, it would only be visible inside of it.
-```
-
-````smart header="`finally` and `return`"
-Finally clause works for *any* exit from `try..catch`. That includes an explicit `return`.
-
-In the example below, there's a `return` in `try`. In this case, `finally` is executed just before the control returns to the outer code.
-
-```js run
-function func() {
-
- try {
-*!*
- return 1;
-*/!*
-
- } catch (e) {
- /* ... */
- } finally {
-*!*
- alert( 'finally' );
-*/!*
- }
-}
-
-alert( func() ); // first works alert from finally, and then this one
-```
-````
-
-````smart header="`try..finally`"
-
-The `try..finally` construct, without `catch` clause, is also useful. We apply it when we don't want to handle errors right here, but want to be sure that processes that we started are finalized.
-
-```js
-function func() {
- // start doing something that needs completion (like measurements)
- try {
- // ...
- } finally {
- // complete that thing even if all dies
- }
-}
-```
-In the code above, an error inside `try` always falls out, because there's no `catch`. But `finally` works before the execution flow jumps outside.
-````
-
-## Global catch
-
-```warn header="Environment-specific"
-The information from this section is not a part of the core JavaScript.
-```
-
-Let's imagine we've got a fatal error outside of `try..catch`, and the script died. Like a programming error or something else terrible.
-
-Is there a way to react on such occurrences? We may want to log the error, show something to the user (normally he doesn't see error messages) etc.
-
-There is none in the specification, but environments usually provide it, because it's really useful. For instance, Node.JS has [process.on('uncaughtException')](https://nodejs.org/api/process.html#process_event_uncaughtexception) for that. And in the browser we can assign a function to special [window.onerror](mdn:api/GlobalEventHandlers/onerror) property. It will run in case of an uncaught error.
-
-The syntax:
-
-```js
-window.onerror = function(message, url, line, col, error) {
- // ...
-};
-```
-
-`message`
-: Error message.
-
-`url`
-: URL of the script where error happened.
-
-`line`, `col`
-: Line and column numbers where error happened.
-
-`error`
-: Error object.
-
-For instance:
-
-```html run untrusted refresh height=1
-
-```
-
-The role of the global handler `window.onerror` is usually not to recover the script execution -- that's probably impossible in case of programming errors, but to send the error message to developers.
-
-There are also web-services that provide error-logging for such cases, like or .
-
-They work like this:
-
-1. We register at the service and get a piece of JS (or a script URL) from them to insert on pages.
-2. That JS script has a custom `window.onerror` function.
-3. When an error occurs, it sends a network request about it to the service.
-4. We can log in to the service web interface and see errors.
-
-## Summary
-
-The `try..catch` construct allows to handle runtime errors. It literally allows to try running the code and catch errors that may occur in it.
-
-The syntax is:
-
-```js
-try {
- // run this code
-} catch(err) {
- // if an error happened, then jump here
- // err is the error object
-} finally {
- // do in any case after try/catch
-}
-```
-
-There may be no `catch` section or no `finally`, so `try..catch` and `try..finally` are also valid.
-
-Error objects have following properties:
-
-- `message` -- the human-readable error message.
-- `name` -- the string with error name (error constructor name).
-- `stack` (non-standard) -- the stack at the moment of error creation.
-
-We can also generate our own errors using the `throw` operator. Technically, the argument of `throw` can be anything, but usually it's an error object inheriting from the built-in `Error` class. More on extending errors in the next chapter.
-
-Rethrowing is a basic pattern of error handling: a `catch` block usually expects and knows how to handle the particular error type, so it should rethrow errors it doesn't know.
-
-Even if we don't have `try..catch`, most environments allow to setup a "global" error handler to catch errors that "fall out". In-browser that's `window.onerror`.
diff --git a/1-js/08-error-handling/1-try-catch/try-catch-flow.png b/1-js/08-error-handling/1-try-catch/try-catch-flow.png
deleted file mode 100644
index 6a91b63295..0000000000
Binary files a/1-js/08-error-handling/1-try-catch/try-catch-flow.png and /dev/null differ
diff --git a/1-js/08-error-handling/1-try-catch/try-catch-flow@2x.png b/1-js/08-error-handling/1-try-catch/try-catch-flow@2x.png
deleted file mode 100644
index 8bf9680fd6..0000000000
Binary files a/1-js/08-error-handling/1-try-catch/try-catch-flow@2x.png and /dev/null differ
diff --git a/1-js/08-error-handling/2-custom-errors/1-format-error/solution.md b/1-js/08-error-handling/2-custom-errors/1-format-error/solution.md
deleted file mode 100644
index bb6b74cfaf..0000000000
--- a/1-js/08-error-handling/2-custom-errors/1-format-error/solution.md
+++ /dev/null
@@ -1,16 +0,0 @@
-```js run untrusted
-class FormatError extends SyntaxError {
- constructor(message) {
- super(message);
- this.name = "FormatError";
- }
-}
-
-let err = new FormatError("formatting error");
-
-alert( err.message ); // formatting error
-alert( err.name ); // FormatError
-alert( err.stack ); // stack
-
-alert( err instanceof SyntaxError ); // true
-```
diff --git a/1-js/08-error-handling/2-custom-errors/article.md b/1-js/08-error-handling/2-custom-errors/article.md
deleted file mode 100644
index d7a780f642..0000000000
--- a/1-js/08-error-handling/2-custom-errors/article.md
+++ /dev/null
@@ -1,307 +0,0 @@
-# Custom errors, extending Error
-
-When we develop something, we often need our own error classes to reflect specific things that may go wrong in our tasks. For errors in network operations we may need `HttpError`, for database operations `DbError`, for searching operations `NotFoundError` and so on.
-
-Our errors should support basic error properties like `message`, `name` and, preferably, `stack`. But they also may have other properties of their own, e.g. `HttpError` objects may have `statusCode` property with a value like `404` or `403` or `500`.
-
-JavaScript allows to use `throw` with any argument, so technically our custom error classes don't need to inherit from `Error`. But if we inherit, then it becomes possible to use `obj instanceof Error` to identify error objects. So it's better to inherit from it.
-
-As we build our application, our own errors naturally form a hierarchy, for instance `HttpTimeoutError` may inherit from `HttpError`, and so on.
-
-## Extending Error
-
-As an example, let's consider a function `readUser(json)` that should read JSON with user data.
-
-Here's an example of how a valid `json` may look:
-```js
-let json = `{ "name": "John", "age": 30 }`;
-```
-
-Internally, we'll use `JSON.parse`. If it receives malformed `json`, then it throws `SyntaxError`.
-
-But even if `json` is syntactically correct, that doesn't mean that it's a valid user, right? It may miss the necessary data. For instance, if may not have `name` and `age` properties that are essential for our users.
-
-Our function `readUser(json)` will not only read JSON, but check ("validate") the data. If there are no required fields, or the format is wrong, then that's an error. And that's not a `SyntaxError`, because the data is syntactically correct, but another kind of error. We'll call it `ValidationError` and create a class for it. An error of that kind should also carry the information about the offending field.
-
-Our `ValidationError` class should inherit from the built-in `Error` class.
-
-That class is built-in, but we should have its approximate code before our eyes, to understand what we're extending.
-
-So here you are:
-
-```js
-// The "pseudocode" for the built-in Error class defined by JavaScript itself
-class Error {
- constructor(message) {
- this.message = message;
- this.name = "Error"; // (different names for different built-in error classes)
- this.stack = ; // non-standard, but most environments support it
- }
-}
-```
-
-Now let's go on and inherit `ValidationError` from it:
-
-```js run untrusted
-*!*
-class ValidationError extends Error {
-*/!*
- constructor(message) {
- super(message); // (1)
- this.name = "ValidationError"; // (2)
- }
-}
-
-function test() {
- throw new ValidationError("Whoops!");
-}
-
-try {
- test();
-} catch(err) {
- alert(err.message); // Whoops!
- alert(err.name); // ValidationError
- alert(err.stack); // a list of nested calls with line numbers for each
-}
-```
-
-Please take a look at the constructor:
-
-1. In the line `(1)` we call the parent constructor. JavaScript requires us to call `super` in the child constructor, so that's obligatory. The parent constructor sets the `message` property.
-2. The parent constructor also sets the `name` property to `"Error"`, so in the line `(2)` we reset it to the right value.
-
-Let's try to use it in `readUser(json)`:
-
-```js run
-class ValidationError extends Error {
- constructor(message) {
- super(message);
- this.name = "ValidationError";
- }
-}
-
-// Usage
-function readUser(json) {
- let user = JSON.parse(json);
-
- if (!user.age) {
- throw new ValidationError("No field: age");
- }
- if (!user.name) {
- throw new ValidationError("No field: name");
- }
-
- return user;
-}
-
-// Working example with try..catch
-
-try {
- let user = readUser('{ "age": 25 }');
-} catch (err) {
- if (err instanceof ValidationError) {
-*!*
- alert("Invalid data: " + err.message); // Invalid data: No field: name
-*/!*
- } else if (err instanceof SyntaxError) { // (*)
- alert("JSON Syntax Error: " + err.message);
- } else {
- throw err; // unknown error, rethrow it (**)
- }
-}
-```
-
-The `try..catch` block in the code above handles both our `ValidationError` and the built-in `SyntaxError` from `JSON.parse`.
-
-Please take a look at how we use `instanceof` to check for the specific error type in the line `(*)`.
-
-We could also look at `err.name`, like this:
-
-```js
-// ...
-// instead of (err instanceof SyntaxError)
-} else if (err.name == "SyntaxError") { // (*)
-// ...
-```
-
-The `instanceof` version is much better, because in the future we are going to extend `ValidationError`, make subtypes of it, like `PropertyRequiredError`. And `instanceof` check will continue to work for new inheriting classes. So that's future-proof.
-
-Also it's important that if `catch` meets an unknown error, then it rethrows it in the line `(**)`. The `catch` only knows how to handle validation and syntax errors, other kinds (due to a typo in the code or such) should fall through.
-
-## Further inheritance
-
-The `ValidationError` class is very generic. Many things may go wrong. The property may be absent or it may be in a wrong format (like a string value for `age`). Let's make a more concrete class `PropertyRequiredError`, exactly for absent properties. It will carry additional information about the property that's missing.
-
-```js run
-class ValidationError extends Error {
- constructor(message) {
- super(message);
- this.name = "ValidationError";
- }
-}
-
-*!*
-class PropertyRequiredError extends ValidationError {
- constructor(property) {
- super("No property: " + property);
- this.name = "PropertyRequiredError";
- this.property = property;
- }
-}
-*/!*
-
-// Usage
-function readUser(json) {
- let user = JSON.parse(json);
-
- if (!user.age) {
- throw new PropertyRequiredError("age");
- }
- if (!user.name) {
- throw new PropertyRequiredError("name");
- }
-
- return user;
-}
-
-// Working example with try..catch
-
-try {
- let user = readUser('{ "age": 25 }');
-} catch (err) {
- if (err instanceof ValidationError) {
-*!*
- alert("Invalid data: " + err.message); // Invalid data: No property: name
- alert(err.name); // PropertyRequiredError
- alert(err.property); // name
-*/!*
- } else if (err instanceof SyntaxError) {
- alert("JSON Syntax Error: " + err.message);
- } else {
- throw err; // unknown error, rethrow it
- }
-}
-```
-
-The new class `PropertyRequiredError` is easy to use: we only need to pass the property name: `new PropertyRequiredError(property)`. The human-readable `message` is generated by the constructor.
-
-Please note that `this.name` in `PropertyRequiredError` constructor is again assigned manually. That may become a bit tedius -- to assign `this.name = ` when creating each custom error. But there's a way out. We can make our own "basic error" class that removes this burden from our shoulders by using `this.constructor.name` for `this.name` in the constructor. And then inherit from it.
-
-Let's call it `MyError`.
-
-Here's the code with `MyError` and other custom error classes, simplified:
-
-```js run
-class MyError extends Error {
- constructor(message) {
- super(message);
-*!*
- this.name = this.constructor.name;
-*/!*
- }
-}
-
-class ValidationError extends MyError { }
-
-class PropertyRequiredError extends ValidationError {
- constructor(property) {
- super("No property: " + property);
- this.property = property;
- }
-}
-
-// name is correct
-alert( new PropertyRequiredError("field").name ); // PropertyRequiredError
-```
-
-Now custom errors are much shorter, especially `ValidationError`, as we got rid of the `"this.name = ..."` line in the constructor.
-
-## Wrapping exceptions
-
-The purpose of the function `readUser` in the code above is "to read the user data", right? There may occur different kinds of errors in the process. Right now we have `SyntaxError` and `ValidationError`, but in the future `readUser` function may grow: the new code will probably generate other kinds of errors.
-
-The code which calls `readUser` should handle these errors. Right now it uses multiple `if` in the `catch` block to check for different error types and rethrow the unknown ones. But if `readUser` function generates several kinds of errors -- then we should ask ourselves: do we really want to check for all error types one-by-one in every code that calls `readUser`?
-
-Often the answer is "No": the outer code wants to be "one level above all that". It wants to have some kind of "data reading error". Why exactly it happened -- is often irrelevant (the error message describes it). Or, even better if there is a way to get error details, but only if we need to.
-
-So let's make a new class `ReadError` to represent such errors. If an error occurs inside `readUser`, we'll catch it there and generate `ReadError`. We'll also keep the reference to the original error in the `cause` property. Then the outer code will only have to check for `ReadError`.
-
-Here's the code that defines `ReadError` and demonstrates its use in `readUser` and `try..catch`:
-
-```js run
-class ReadError extends Error {
- constructor(message, cause) {
- super(message);
- this.cause = cause;
- this.name = 'ReadError';
- }
-}
-
-class ValidationError extends Error { /*...*/ }
-class PropertyRequiredError extends ValidationError { /* ... */ }
-
-function validateUser(user) {
- if (!user.age) {
- throw new PropertyRequiredError("age");
- }
-
- if (!user.name) {
- throw new PropertyRequiredError("name");
- }
-}
-
-function readUser(json) {
- let user;
-
- try {
- user = JSON.parse(json);
- } catch (err) {
-*!*
- if (err instanceof SyntaxError) {
- throw new ReadError("Syntax Error", err);
- } else {
- throw err;
- }
-*/!*
- }
-
- try {
- validateUser(user);
- } catch (err) {
-*!*
- if (err instanceof ValidationError) {
- throw new ReadError("Validation Error", err);
- } else {
- throw err;
- }
-*/!*
- }
-
-}
-
-try {
- readUser('{bad json}');
-} catch (e) {
- if (e instanceof ReadError) {
-*!*
- alert(e);
- // Original error: SyntaxError: Unexpected token b in JSON at position 1
- alert("Original error: " + e.cause);
-*/!*
- } else {
- throw e;
- }
-}
-```
-
-In the code above, `readUser` works exactly as described -- catches syntax and validation errors and throws `ReadError` errors instead (unknown errors are rethrown as usual).
-
-So the outer code checks `instanceof ReadError` and that's it. No need to list possible all error types.
-
-The approach is called "wrapping exceptions", because we take "low level exceptions" and "wrap" them into `ReadError` that is more abstract and more convenient to use for the calling code. It is widely used in object-oriented programming.
-
-## Summary
-
-- We can inherit from `Error` and other built-in error classes normally, just need to take care of `name` property and don't forget to call `super`.
-- Most of the time, we should use `instanceof` to check for particular errors. It also works with inheritance. But sometimes we have an error object coming from the 3rd-party library and there's no easy way to get the class. Then `name` property can be used for such checks.
-- Wrapping exceptions is a widespread technique when a function handles low-level exceptions and makes a higher-level object to report about the errors. Low-level exceptions sometimes become properties of that object like `err.cause` in the examples above, but that's not strictly required.
diff --git a/1-js/07-object-oriented-programming/03-prototype-inheritance/1-property-after-delete/solution.md b/1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/solution.md
similarity index 100%
rename from 1-js/07-object-oriented-programming/03-prototype-inheritance/1-property-after-delete/solution.md
rename to 1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/solution.md
diff --git a/1-js/07-object-oriented-programming/03-prototype-inheritance/1-property-after-delete/task.md b/1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/task.md
similarity index 100%
rename from 1-js/07-object-oriented-programming/03-prototype-inheritance/1-property-after-delete/task.md
rename to 1-js/08-prototypes/01-prototype-inheritance/1-property-after-delete/task.md
diff --git a/1-js/07-object-oriented-programming/03-prototype-inheritance/2-search-algorithm/solution.md b/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/solution.md
similarity index 100%
rename from 1-js/07-object-oriented-programming/03-prototype-inheritance/2-search-algorithm/solution.md
rename to 1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/solution.md
diff --git a/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/task.md b/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/task.md
new file mode 100644
index 0000000000..bc2db47fed
--- /dev/null
+++ b/1-js/08-prototypes/01-prototype-inheritance/2-search-algorithm/task.md
@@ -0,0 +1,31 @@
+importance: 5
+
+---
+
+# Searching algorithm
+
+The task has two parts.
+
+Given the following objects:
+
+```js
+let head = {
+ glasses: 1
+};
+
+let table = {
+ pen: 3
+};
+
+let bed = {
+ sheet: 1,
+ pillow: 2
+};
+
+let pockets = {
+ money: 2000
+};
+```
+
+1. Use `__proto__` to assign prototypes in a way that any property lookup will follow the path: `pockets` -> `bed` -> `table` -> `head`. For instance, `pockets.pen` should be `3` (found in `table`), and `bed.glasses` should be `1` (found in `head`).
+2. Answer the question: is it faster to get `glasses` as `pockets.glasses` or `head.glasses`? Benchmark if needed.
diff --git a/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/solution.md b/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/solution.md
new file mode 100644
index 0000000000..4d6ea2653c
--- /dev/null
+++ b/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/solution.md
@@ -0,0 +1,7 @@
+**The answer: `rabbit`.**
+
+That's because `this` is an object before the dot, so `rabbit.eat()` modifies `rabbit`.
+
+Property lookup and execution are two different things.
+
+The method `rabbit.eat` is first found in the prototype, then executed with `this=rabbit`.
diff --git a/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/task.md b/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/task.md
new file mode 100644
index 0000000000..ed8482c072
--- /dev/null
+++ b/1-js/08-prototypes/01-prototype-inheritance/3-proto-and-this/task.md
@@ -0,0 +1,23 @@
+importance: 5
+
+---
+
+# Where does it write?
+
+We have `rabbit` inheriting from `animal`.
+
+If we call `rabbit.eat()`, which object receives the `full` property: `animal` or `rabbit`?
+
+```js
+let animal = {
+ eat() {
+ this.full = true;
+ }
+};
+
+let rabbit = {
+ __proto__: animal
+};
+
+rabbit.eat();
+```
diff --git a/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md
new file mode 100644
index 0000000000..c141b2ecdc
--- /dev/null
+++ b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/solution.md
@@ -0,0 +1,80 @@
+Let's look carefully at what's going on in the call `speedy.eat("apple")`.
+
+1. The method `speedy.eat` is found in the prototype (`=hamster`), then executed with `this=speedy` (the object before the dot).
+
+2. Then `this.stomach.push()` needs to find `stomach` property and call `push` on it. It looks for `stomach` in `this` (`=speedy`), but nothing found.
+
+3. Then it follows the prototype chain and finds `stomach` in `hamster`.
+
+4. Then it calls `push` on it, adding the food into *the stomach of the prototype*.
+
+So all hamsters share a single stomach!
+
+Both for `lazy.stomach.push(...)` and `speedy.stomach.push()`, the property `stomach` is found in the prototype (as it's not in the object itself), then the new data is pushed into it.
+
+Please note that such thing doesn't happen in case of a simple assignment `this.stomach=`:
+
+```js run
+let hamster = {
+ stomach: [],
+
+ eat(food) {
+*!*
+ // assign to this.stomach instead of this.stomach.push
+ this.stomach = [food];
+*/!*
+ }
+};
+
+let speedy = {
+ __proto__: hamster
+};
+
+let lazy = {
+ __proto__: hamster
+};
+
+// Speedy one found the food
+speedy.eat("apple");
+alert( speedy.stomach ); // apple
+
+// Lazy one's stomach is empty
+alert( lazy.stomach ); //
+```
+
+Now all works fine, because `this.stomach=` does not perform a lookup of `stomach`. The value is written directly into `this` object.
+
+Also we can totally avoid the problem by making sure that each hamster has their own stomach:
+
+```js run
+let hamster = {
+ stomach: [],
+
+ eat(food) {
+ this.stomach.push(food);
+ }
+};
+
+let speedy = {
+ __proto__: hamster,
+*!*
+ stomach: []
+*/!*
+};
+
+let lazy = {
+ __proto__: hamster,
+*!*
+ stomach: []
+*/!*
+};
+
+// Speedy one found the food
+speedy.eat("apple");
+alert( speedy.stomach ); // apple
+
+// Lazy one's stomach is empty
+alert( lazy.stomach ); //
+```
+
+As a common solution, all properties that describe the state of a particular object, like `stomach` above, should be written into that object. That prevents such problems.
diff --git a/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/task.md b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/task.md
new file mode 100644
index 0000000000..50171123d4
--- /dev/null
+++ b/1-js/08-prototypes/01-prototype-inheritance/4-hamster-proto/task.md
@@ -0,0 +1,35 @@
+importance: 5
+
+---
+
+# Why are both hamsters full?
+
+We have two hamsters: `speedy` and `lazy` inheriting from the general `hamster` object.
+
+When we feed one of them, the other one is also full. Why? How can we fix it?
+
+```js run
+let hamster = {
+ stomach: [],
+
+ eat(food) {
+ this.stomach.push(food);
+ }
+};
+
+let speedy = {
+ __proto__: hamster
+};
+
+let lazy = {
+ __proto__: hamster
+};
+
+// This one found the food
+speedy.eat("apple");
+alert( speedy.stomach ); // apple
+
+// This one also has it, why? fix please.
+alert( lazy.stomach ); // apple
+```
+
diff --git a/1-js/08-prototypes/01-prototype-inheritance/article.md b/1-js/08-prototypes/01-prototype-inheritance/article.md
new file mode 100644
index 0000000000..ef6c7ffebd
--- /dev/null
+++ b/1-js/08-prototypes/01-prototype-inheritance/article.md
@@ -0,0 +1,338 @@
+# Prototypal inheritance
+
+In programming, we often want to take something and extend it.
+
+For instance, we have a `user` object with its properties and methods, and want to make `admin` and `guest` as slightly modified variants of it. We'd like to reuse what we have in `user`, not copy/reimplement its methods, just build a new object on top of it.
+
+*Prototypal inheritance* is a language feature that helps in that.
+
+## [[Prototype]]
+
+In JavaScript, objects have a special hidden property `[[Prototype]]` (as named in the specification), that is either `null` or references another object. That object is called "a prototype":
+
+
+
+When we read a property from `object`, and it's missing, JavaScript automatically takes it from the prototype. In programming, this is called "prototypal inheritance". And soon we'll study many examples of such inheritance, as well as cooler language features built upon it.
+
+The property `[[Prototype]]` is internal and hidden, but there are many ways to set it.
+
+One of them is to use the special name `__proto__`, like this:
+
+```js run
+let animal = {
+ eats: true
+};
+let rabbit = {
+ jumps: true
+};
+
+*!*
+rabbit.__proto__ = animal; // sets rabbit.[[Prototype]] = animal
+*/!*
+```
+
+Now if we read a property from `rabbit`, and it's missing, JavaScript will automatically take it from `animal`.
+
+For instance:
+
+```js
+let animal = {
+ eats: true
+};
+let rabbit = {
+ jumps: true
+};
+
+*!*
+rabbit.__proto__ = animal; // (*)
+*/!*
+
+// we can find both properties in rabbit now:
+*!*
+alert( rabbit.eats ); // true (**)
+*/!*
+alert( rabbit.jumps ); // true
+```
+
+Here the line `(*)` sets `animal` to be the prototype of `rabbit`.
+
+Then, when `alert` tries to read property `rabbit.eats` `(**)`, it's not in `rabbit`, so JavaScript follows the `[[Prototype]]` reference and finds it in `animal` (look from the bottom up):
+
+
+
+Here we can say that "`animal` is the prototype of `rabbit`" or "`rabbit` prototypically inherits from `animal`".
+
+So if `animal` has a lot of useful properties and methods, then they become automatically available in `rabbit`. Such properties are called "inherited".
+
+If we have a method in `animal`, it can be called on `rabbit`:
+
+```js run
+let animal = {
+ eats: true,
+*!*
+ walk() {
+ alert("Animal walk");
+ }
+*/!*
+};
+
+let rabbit = {
+ jumps: true,
+ __proto__: animal
+};
+
+// walk is taken from the prototype
+*!*
+rabbit.walk(); // Animal walk
+*/!*
+```
+
+The method is automatically taken from the prototype, like this:
+
+
+
+The prototype chain can be longer:
+
+```js run
+let animal = {
+ eats: true,
+ walk() {
+ alert("Animal walk");
+ }
+};
+
+let rabbit = {
+ jumps: true,
+*!*
+ __proto__: animal
+*/!*
+};
+
+let longEar = {
+ earLength: 10,
+*!*
+ __proto__: rabbit
+*/!*
+};
+
+// walk is taken from the prototype chain
+longEar.walk(); // Animal walk
+alert(longEar.jumps); // true (from rabbit)
+```
+
+
+
+Now if we read something from `longEar`, and it's missing, JavaScript will look for it in `rabbit`, and then in `animal`.
+
+There are only two limitations:
+
+1. The references can't go in circles. JavaScript will throw an error if we try to assign `__proto__` in a circle.
+2. The value of `__proto__` can be either an object or `null`. Other types are ignored.
+
+Also it may be obvious, but still: there can be only one `[[Prototype]]`. An object may not inherit from two others.
+
+```smart header="`__proto__` is a historical getter/setter for `[[Prototype]]`"
+It's a common mistake of novice developers not to know the difference between these two.
+
+Please note that `__proto__` is *not the same* as the internal `[[Prototype]]` property. It's a getter/setter for `[[Prototype]]`. Later we'll see situations where it matters, for now let's just keep it in mind, as we build our understanding of JavaScript language.
+
+The `__proto__` property is a bit outdated. It exists for historical reasons, modern JavaScript suggests that we should use `Object.getPrototypeOf/Object.setPrototypeOf` functions instead that get/set the prototype. We'll also cover these functions later.
+
+By the specification, `__proto__` must only be supported by browsers. In fact though, all environments including server-side support `__proto__`, so we're quite safe using it.
+
+As the `__proto__` notation is a bit more intuitively obvious, we use it in the examples.
+```
+
+## Writing doesn't use prototype
+
+The prototype is only used for reading properties.
+
+Write/delete operations work directly with the object.
+
+In the example below, we assign its own `walk` method to `rabbit`:
+
+```js run
+let animal = {
+ eats: true,
+ walk() {
+ /* this method won't be used by rabbit */
+ }
+};
+
+let rabbit = {
+ __proto__: animal
+};
+
+*!*
+rabbit.walk = function() {
+ alert("Rabbit! Bounce-bounce!");
+};
+*/!*
+
+rabbit.walk(); // Rabbit! Bounce-bounce!
+```
+
+From now on, `rabbit.walk()` call finds the method immediately in the object and executes it, without using the prototype:
+
+
+
+Accessor properties are an exception, as assignment is handled by a setter function. So writing to such a property is actually the same as calling a function.
+
+For that reason `admin.fullName` works correctly in the code below:
+
+```js run
+let user = {
+ name: "John",
+ surname: "Smith",
+
+ set fullName(value) {
+ [this.name, this.surname] = value.split(" ");
+ },
+
+ get fullName() {
+ return `${this.name} ${this.surname}`;
+ }
+};
+
+let admin = {
+ __proto__: user,
+ isAdmin: true
+};
+
+alert(admin.fullName); // John Smith (*)
+
+// setter triggers!
+admin.fullName = "Alice Cooper"; // (**)
+
+alert(admin.fullName); // Alice Cooper, state of admin modified
+alert(user.fullName); // John Smith, state of user protected
+```
+
+Here in the line `(*)` the property `admin.fullName` has a getter in the prototype `user`, so it is called. And in the line `(**)` the property has a setter in the prototype, so it is called.
+
+## The value of "this"
+
+An interesting question may arise in the example above: what's the value of `this` inside `set fullName(value)`? Where are the properties `this.name` and `this.surname` written: into `user` or `admin`?
+
+The answer is simple: `this` is not affected by prototypes at all.
+
+**No matter where the method is found: in an object or its prototype. In a method call, `this` is always the object before the dot.**
+
+So, the setter call `admin.fullName=` uses `admin` as `this`, not `user`.
+
+That is actually a super-important thing, because we may have a big object with many methods, and have objects that inherit from it. And when the inheriting objects run the inherited methods, they will modify only their own states, not the state of the big object.
+
+For instance, here `animal` represents a "method storage", and `rabbit` makes use of it.
+
+The call `rabbit.sleep()` sets `this.isSleeping` on the `rabbit` object:
+
+```js run
+// animal has methods
+let animal = {
+ walk() {
+ if (!this.isSleeping) {
+ alert(`I walk`);
+ }
+ },
+ sleep() {
+ this.isSleeping = true;
+ }
+};
+
+let rabbit = {
+ name: "White Rabbit",
+ __proto__: animal
+};
+
+// modifies rabbit.isSleeping
+rabbit.sleep();
+
+alert(rabbit.isSleeping); // true
+alert(animal.isSleeping); // undefined (no such property in the prototype)
+```
+
+The resulting picture:
+
+
+
+If we had other objects, like `bird`, `snake`, etc., inheriting from `animal`, they would also gain access to methods of `animal`. But `this` in each method call would be the corresponding object, evaluated at the call-time (before dot), not `animal`. So when we write data into `this`, it is stored into these objects.
+
+As a result, methods are shared, but the object state is not.
+
+## for..in loop
+
+The `for..in` loop iterates over inherited properties too.
+
+For instance:
+
+```js run
+let animal = {
+ eats: true
+};
+
+let rabbit = {
+ jumps: true,
+ __proto__: animal
+};
+
+*!*
+// Object.keys only returns own keys
+alert(Object.keys(rabbit)); // jumps
+*/!*
+
+*!*
+// for..in loops over both own and inherited keys
+for(let prop in rabbit) alert(prop); // jumps, then eats
+*/!*
+```
+
+If that's not what we want, and we'd like to exclude inherited properties, there's a built-in method [obj.hasOwnProperty(key)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty): it returns `true` if `obj` has its own (not inherited) property named `key`.
+
+So we can filter out inherited properties (or do something else with them):
+
+```js run
+let animal = {
+ eats: true
+};
+
+let rabbit = {
+ jumps: true,
+ __proto__: animal
+};
+
+for(let prop in rabbit) {
+ let isOwn = rabbit.hasOwnProperty(prop);
+
+ if (isOwn) {
+ alert(`Our: ${prop}`); // Our: jumps
+ } else {
+ alert(`Inherited: ${prop}`); // Inherited: eats
+ }
+}
+```
+
+Here we have the following inheritance chain: `rabbit` inherits from `animal`, that inherits from `Object.prototype` (because `animal` is a literal object `{...}`, so it's by default), and then `null` above it:
+
+
+
+Note, there's one funny thing. Where is the method `rabbit.hasOwnProperty` coming from? We did not define it. Looking at the chain we can see that the method is provided by `Object.prototype.hasOwnProperty`. In other words, it's inherited.
+
+...But why does `hasOwnProperty` not appear in the `for..in` loop like `eats` and `jumps` do, if `for..in` lists inherited properties?
+
+The answer is simple: it's not enumerable. Just like all other properties of `Object.prototype`, it has `enumerable:false` flag. And `for..in` only lists enumerable properties. That's why it and the rest of the `Object.prototype` properties are not listed.
+
+```smart header="Almost all other key/value-getting methods ignore inherited properties"
+Almost all other key/value-getting methods, such as `Object.keys`, `Object.values` and so on ignore inherited properties.
+
+They only operate on the object itself. Properties from the prototype are *not* taken into account.
+```
+
+## Summary
+
+- In JavaScript, all objects have a hidden `[[Prototype]]` property that's either another object or `null`.
+- We can use `obj.__proto__` to access it (a historical getter/setter, there are other ways, to be covered soon).
+- The object referenced by `[[Prototype]]` is called a "prototype".
+- If we want to read a property of `obj` or call a method, and it doesn't exist, then JavaScript tries to find it in the prototype.
+- Write/delete operations act directly on the object, they don't use the prototype (assuming it's a data property, not a setter).
+- If we call `obj.method()`, and the `method` is taken from the prototype, `this` still references `obj`. So methods always work with the current object even if they are inherited.
+- The `for..in` loop iterates over both its own and its inherited properties. All other key/value-getting methods only operate on the object itself.
diff --git a/1-js/08-prototypes/01-prototype-inheritance/object-prototype-empty.svg b/1-js/08-prototypes/01-prototype-inheritance/object-prototype-empty.svg
new file mode 100644
index 0000000000..eb79c19ffd
--- /dev/null
+++ b/1-js/08-prototypes/01-prototype-inheritance/object-prototype-empty.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit-chain.svg b/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit-chain.svg
new file mode 100644
index 0000000000..4bf580ae77
--- /dev/null
+++ b/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit-chain.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit-walk-2.svg b/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit-walk-2.svg
new file mode 100644
index 0000000000..838c78395b
--- /dev/null
+++ b/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit-walk-2.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit-walk-3.svg b/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit-walk-3.svg
new file mode 100644
index 0000000000..d791e5390d
--- /dev/null
+++ b/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit-walk-3.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit-walk.svg b/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit-walk.svg
new file mode 100644
index 0000000000..b324710286
--- /dev/null
+++ b/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit-walk.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit.svg b/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit.svg
new file mode 100644
index 0000000000..4f3c1bc0ec
--- /dev/null
+++ b/1-js/08-prototypes/01-prototype-inheritance/proto-animal-rabbit.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/08-prototypes/01-prototype-inheritance/proto-user-admin.svg b/1-js/08-prototypes/01-prototype-inheritance/proto-user-admin.svg
new file mode 100644
index 0000000000..bf0baf013a
--- /dev/null
+++ b/1-js/08-prototypes/01-prototype-inheritance/proto-user-admin.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/08-prototypes/01-prototype-inheritance/rabbit-animal-object.svg b/1-js/08-prototypes/01-prototype-inheritance/rabbit-animal-object.svg
new file mode 100644
index 0000000000..32a9858f83
--- /dev/null
+++ b/1-js/08-prototypes/01-prototype-inheritance/rabbit-animal-object.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/08-prototypes/02-function-prototype/1-changing-prototype/solution.md b/1-js/08-prototypes/02-function-prototype/1-changing-prototype/solution.md
new file mode 100644
index 0000000000..ebbdf3a7c1
--- /dev/null
+++ b/1-js/08-prototypes/02-function-prototype/1-changing-prototype/solution.md
@@ -0,0 +1,20 @@
+
+Answers:
+
+1. `true`.
+
+ The assignment to `Rabbit.prototype` sets up `[[Prototype]]` for new objects, but it does not affect the existing ones.
+
+2. `false`.
+
+ Objects are assigned by reference. The object from `Rabbit.prototype` is not duplicated, it's still a single object referenced both by `Rabbit.prototype` and by the `[[Prototype]]` of `rabbit`.
+
+ So when we change its content through one reference, it is visible through the other one.
+
+3. `true`.
+
+ All `delete` operations are applied directly to the object. Here `delete rabbit.eats` tries to remove `eats` property from `rabbit`, but it doesn't have it. So the operation won't have any effect.
+
+4. `undefined`.
+
+ The property `eats` is deleted from the prototype, it doesn't exist any more.
diff --git a/1-js/08-prototypes/02-function-prototype/1-changing-prototype/task.md b/1-js/08-prototypes/02-function-prototype/1-changing-prototype/task.md
new file mode 100644
index 0000000000..2838c125ad
--- /dev/null
+++ b/1-js/08-prototypes/02-function-prototype/1-changing-prototype/task.md
@@ -0,0 +1,89 @@
+importance: 5
+
+---
+
+# Changing "prototype"
+
+In the code below we create `new Rabbit`, and then try to modify its prototype.
+
+In the start, we have this code:
+
+```js run
+function Rabbit() {}
+Rabbit.prototype = {
+ eats: true
+};
+
+let rabbit = new Rabbit();
+
+alert( rabbit.eats ); // true
+```
+
+
+1. We added one more string (emphasized). What will `alert` show now?
+
+ ```js
+ function Rabbit() {}
+ Rabbit.prototype = {
+ eats: true
+ };
+
+ let rabbit = new Rabbit();
+
+ *!*
+ Rabbit.prototype = {};
+ */!*
+
+ alert( rabbit.eats ); // ?
+ ```
+
+2. ...And if the code is like this (replaced one line)?
+
+ ```js
+ function Rabbit() {}
+ Rabbit.prototype = {
+ eats: true
+ };
+
+ let rabbit = new Rabbit();
+
+ *!*
+ Rabbit.prototype.eats = false;
+ */!*
+
+ alert( rabbit.eats ); // ?
+ ```
+
+3. And like this (replaced one line)?
+
+ ```js
+ function Rabbit() {}
+ Rabbit.prototype = {
+ eats: true
+ };
+
+ let rabbit = new Rabbit();
+
+ *!*
+ delete rabbit.eats;
+ */!*
+
+ alert( rabbit.eats ); // ?
+ ```
+
+4. The last variant:
+
+ ```js
+ function Rabbit() {}
+ Rabbit.prototype = {
+ eats: true
+ };
+
+ let rabbit = new Rabbit();
+
+ *!*
+ delete Rabbit.prototype.eats;
+ */!*
+
+ alert( rabbit.eats ); // ?
+ ```
diff --git a/1-js/08-prototypes/02-function-prototype/4-new-object-same-constructor/solution.md b/1-js/08-prototypes/02-function-prototype/4-new-object-same-constructor/solution.md
new file mode 100644
index 0000000000..372d50dd6d
--- /dev/null
+++ b/1-js/08-prototypes/02-function-prototype/4-new-object-same-constructor/solution.md
@@ -0,0 +1,49 @@
+We can use such approach if we are sure that `"constructor"` property has the correct value.
+
+For instance, if we don't touch the default `"prototype"`, then this code works for sure:
+
+```js run
+function User(name) {
+ this.name = name;
+}
+
+let user = new User('John');
+let user2 = new user.constructor('Pete');
+
+alert( user2.name ); // Pete (worked!)
+```
+
+It worked, because `User.prototype.constructor == User`.
+
+..But if someone, so to speak, overwrites `User.prototype` and forgets to recreate `constructor` to reference `User`, then it would fail.
+
+For instance:
+
+```js run
+function User(name) {
+ this.name = name;
+}
+*!*
+User.prototype = {}; // (*)
+*/!*
+
+let user = new User('John');
+let user2 = new user.constructor('Pete');
+
+alert( user2.name ); // undefined
+```
+
+Why `user2.name` is `undefined`?
+
+Here's how `new user.constructor('Pete')` works:
+
+1. First, it looks for `constructor` in `user`. Nothing.
+2. Then it follows the prototype chain. The prototype of `user` is `User.prototype`, and it also has no `constructor` (because we "forgot" to set it right!).
+3. Going further up the chain, `User.prototype` is a plain object, its prototype is the built-in `Object.prototype`.
+4. Finally, for the built-in `Object.prototype`, there's a built-in `Object.prototype.constructor == Object`. So it is used.
+
+Finally, at the end, we have `let user2 = new Object('Pete')`.
+
+Probably, that's not what we want. We'd like to create `new User`, not `new Object`. That's the outcome of the missing `constructor`.
+
+(Just in case you're curious, the `new Object(...)` call converts its argument to an object. That's a theoretical thing, in practice no one calls `new Object` with a value, and generally we don't use `new Object` to make objects at all).
\ No newline at end of file
diff --git a/1-js/07-object-oriented-programming/04-function-prototype/4-new-object-same-constructor/task.md b/1-js/08-prototypes/02-function-prototype/4-new-object-same-constructor/task.md
similarity index 100%
rename from 1-js/07-object-oriented-programming/04-function-prototype/4-new-object-same-constructor/task.md
rename to 1-js/08-prototypes/02-function-prototype/4-new-object-same-constructor/task.md
diff --git a/1-js/08-prototypes/02-function-prototype/article.md b/1-js/08-prototypes/02-function-prototype/article.md
new file mode 100644
index 0000000000..b1ef518266
--- /dev/null
+++ b/1-js/08-prototypes/02-function-prototype/article.md
@@ -0,0 +1,175 @@
+# F.prototype
+
+Remember, new objects can be created with a constructor function, like `new F()`.
+
+If `F.prototype` is an object, then the `new` operator uses it to set `[[Prototype]]` for the new object.
+
+```smart
+JavaScript had prototypal inheritance from the beginning. It was one of the core features of the language.
+
+But in the old times, there was no direct access to it. The only thing that worked reliably was a `"prototype"` property of the constructor function, described in this chapter. So there are many scripts that still use it.
+```
+
+Please note that `F.prototype` here means a regular property named `"prototype"` on `F`. It sounds something similar to the term "prototype", but here we really mean a regular property with this name.
+
+Here's the example:
+
+```js run
+let animal = {
+ eats: true
+};
+
+function Rabbit(name) {
+ this.name = name;
+}
+
+*!*
+Rabbit.prototype = animal;
+*/!*
+
+let rabbit = new Rabbit("White Rabbit"); // rabbit.__proto__ == animal
+
+alert( rabbit.eats ); // true
+```
+
+Setting `Rabbit.prototype = animal` literally states the following: "When a `new Rabbit` is created, assign its `[[Prototype]]` to `animal`".
+
+That's the resulting picture:
+
+
+
+On the picture, `"prototype"` is a horizontal arrow, meaning a regular property, and `[[Prototype]]` is vertical, meaning the inheritance of `rabbit` from `animal`.
+
+```smart header="`F.prototype` only used at `new F` time"
+`F.prototype` property is only used when `new F` is called, it assigns `[[Prototype]]` of the new object.
+
+If, after the creation, `F.prototype` property changes (`F.prototype = `), then new objects created by `new F` will have another object as `[[Prototype]]`, but already existing objects keep the old one.
+```
+
+## Default F.prototype, constructor property
+
+Every function has the `"prototype"` property even if we don't supply it.
+
+The default `"prototype"` is an object with the only property `constructor` that points back to the function itself.
+
+Like this:
+
+```js
+function Rabbit() {}
+
+/* default prototype
+Rabbit.prototype = { constructor: Rabbit };
+*/
+```
+
+
+
+We can check it:
+
+```js run
+function Rabbit() {}
+// by default:
+// Rabbit.prototype = { constructor: Rabbit }
+
+alert( Rabbit.prototype.constructor == Rabbit ); // true
+```
+
+Naturally, if we do nothing, the `constructor` property is available to all rabbits through `[[Prototype]]`:
+
+```js run
+function Rabbit() {}
+// by default:
+// Rabbit.prototype = { constructor: Rabbit }
+
+let rabbit = new Rabbit(); // inherits from {constructor: Rabbit}
+
+alert(rabbit.constructor == Rabbit); // true (from prototype)
+```
+
+
+
+We can use `constructor` property to create a new object using the same constructor as the existing one.
+
+Like here:
+
+```js run
+function Rabbit(name) {
+ this.name = name;
+ alert(name);
+}
+
+let rabbit = new Rabbit("White Rabbit");
+
+*!*
+let rabbit2 = new rabbit.constructor("Black Rabbit");
+*/!*
+```
+
+That's handy when we have an object, don't know which constructor was used for it (e.g. it comes from a 3rd party library), and we need to create another one of the same kind.
+
+But probably the most important thing about `"constructor"` is that...
+
+**...JavaScript itself does not ensure the right `"constructor"` value.**
+
+Yes, it exists in the default `"prototype"` for functions, but that's all. What happens with it later -- is totally on us.
+
+In particular, if we replace the default prototype as a whole, then there will be no `"constructor"` in it.
+
+For instance:
+
+```js run
+function Rabbit() {}
+Rabbit.prototype = {
+ jumps: true
+};
+
+let rabbit = new Rabbit();
+*!*
+alert(rabbit.constructor === Rabbit); // false
+*/!*
+```
+
+So, to keep the right `"constructor"` we can choose to add/remove properties to the default `"prototype"` instead of overwriting it as a whole:
+
+```js
+function Rabbit() {}
+
+// Not overwrite Rabbit.prototype totally
+// just add to it
+Rabbit.prototype.jumps = true
+// the default Rabbit.prototype.constructor is preserved
+```
+
+Or, alternatively, recreate the `constructor` property manually:
+
+```js
+Rabbit.prototype = {
+ jumps: true,
+*!*
+ constructor: Rabbit
+*/!*
+};
+
+// now constructor is also correct, because we added it
+```
+
+
+## Summary
+
+In this chapter we briefly described the way of setting a `[[Prototype]]` for objects created via a constructor function. Later we'll see more advanced programming patterns that rely on it.
+
+Everything is quite simple, just a few notes to make things clear:
+
+- The `F.prototype` property (don't mistake it for `[[Prototype]]`) sets `[[Prototype]]` of new objects when `new F()` is called.
+- The value of `F.prototype` should be either an object or `null`: other values won't work.
+- The `"prototype"` property only has such a special effect when set on a constructor function, and invoked with `new`.
+
+On regular objects the `prototype` is nothing special:
+```js
+let user = {
+ name: "John",
+ prototype: "Bla-bla" // no magic at all
+};
+```
+
+By default all functions have `F.prototype = { constructor: F }`, so we can get the constructor of an object by accessing its `"constructor"` property.
diff --git a/1-js/08-prototypes/02-function-prototype/function-prototype-constructor.svg b/1-js/08-prototypes/02-function-prototype/function-prototype-constructor.svg
new file mode 100644
index 0000000000..59d60b397a
--- /dev/null
+++ b/1-js/08-prototypes/02-function-prototype/function-prototype-constructor.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/08-prototypes/02-function-prototype/proto-constructor-animal-rabbit.svg b/1-js/08-prototypes/02-function-prototype/proto-constructor-animal-rabbit.svg
new file mode 100644
index 0000000000..ede4e1227e
--- /dev/null
+++ b/1-js/08-prototypes/02-function-prototype/proto-constructor-animal-rabbit.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/08-prototypes/02-function-prototype/rabbit-prototype-constructor.svg b/1-js/08-prototypes/02-function-prototype/rabbit-prototype-constructor.svg
new file mode 100644
index 0000000000..54b3d79804
--- /dev/null
+++ b/1-js/08-prototypes/02-function-prototype/rabbit-prototype-constructor.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/07-object-oriented-programming/05-native-prototypes/1-defer-to-prototype/solution.md b/1-js/08-prototypes/03-native-prototypes/1-defer-to-prototype/solution.md
similarity index 100%
rename from 1-js/07-object-oriented-programming/05-native-prototypes/1-defer-to-prototype/solution.md
rename to 1-js/08-prototypes/03-native-prototypes/1-defer-to-prototype/solution.md
diff --git a/1-js/07-object-oriented-programming/05-native-prototypes/1-defer-to-prototype/task.md b/1-js/08-prototypes/03-native-prototypes/1-defer-to-prototype/task.md
similarity index 100%
rename from 1-js/07-object-oriented-programming/05-native-prototypes/1-defer-to-prototype/task.md
rename to 1-js/08-prototypes/03-native-prototypes/1-defer-to-prototype/task.md
diff --git a/1-js/08-prototypes/03-native-prototypes/2-defer-to-prototype-extended/solution.md b/1-js/08-prototypes/03-native-prototypes/2-defer-to-prototype-extended/solution.md
new file mode 100644
index 0000000000..99c358c9b0
--- /dev/null
+++ b/1-js/08-prototypes/03-native-prototypes/2-defer-to-prototype-extended/solution.md
@@ -0,0 +1,41 @@
+
+
+```js run
+Function.prototype.defer = function(ms) {
+ let f = this;
+ return function(...args) {
+ setTimeout(() => f.apply(this, args), ms);
+ }
+};
+
+// check it
+function f(a, b) {
+ alert( a + b );
+}
+
+f.defer(1000)(1, 2); // shows 3 after 1 sec
+```
+
+Please note: we use `this` in `f.apply` to make our decoration work for object methods.
+
+So if the wrapper function is called as an object method, then `this` is passed to the original method `f`.
+
+```js run
+Function.prototype.defer = function(ms) {
+ let f = this;
+ return function(...args) {
+ setTimeout(() => f.apply(this, args), ms);
+ }
+};
+
+let user = {
+ name: "John",
+ sayHi() {
+ alert(this.name);
+ }
+}
+
+user.sayHi = user.sayHi.defer(1000);
+
+user.sayHi();
+```
diff --git a/1-js/07-object-oriented-programming/05-native-prototypes/2-defer-to-prototype-extended/task.md b/1-js/08-prototypes/03-native-prototypes/2-defer-to-prototype-extended/task.md
similarity index 100%
rename from 1-js/07-object-oriented-programming/05-native-prototypes/2-defer-to-prototype-extended/task.md
rename to 1-js/08-prototypes/03-native-prototypes/2-defer-to-prototype-extended/task.md
diff --git a/1-js/08-prototypes/03-native-prototypes/article.md b/1-js/08-prototypes/03-native-prototypes/article.md
new file mode 100644
index 0000000000..bdfc86dd8d
--- /dev/null
+++ b/1-js/08-prototypes/03-native-prototypes/article.md
@@ -0,0 +1,198 @@
+# Native prototypes
+
+The `"prototype"` property is widely used by the core of JavaScript itself. All built-in constructor functions use it.
+
+First we'll look at the details, and then how to use it for adding new capabilities to built-in objects.
+
+## Object.prototype
+
+Let's say we output an empty object:
+
+```js run
+let obj = {};
+alert( obj ); // "[object Object]" ?
+```
+
+Where's the code that generates the string `"[object Object]"`? That's a built-in `toString` method, but where is it? The `obj` is empty!
+
+...But the short notation `obj = {}` is the same as `obj = new Object()`, where `Object` is a built-in object constructor function, with its own `prototype` referencing a huge object with `toString` and other methods.
+
+Here's what's going on:
+
+
+
+When `new Object()` is called (or a literal object `{...}` is created), the `[[Prototype]]` of it is set to `Object.prototype` according to the rule that we discussed in the previous chapter:
+
+
+
+So then when `obj.toString()` is called the method is taken from `Object.prototype`.
+
+We can check it like this:
+
+```js run
+let obj = {};
+
+alert(obj.__proto__ === Object.prototype); // true
+
+alert(obj.toString === obj.__proto__.toString); //true
+alert(obj.toString === Object.prototype.toString); //true
+```
+
+Please note that there is no more `[[Prototype]]` in the chain above `Object.prototype`:
+
+```js run
+alert(Object.prototype.__proto__); // null
+```
+
+## Other built-in prototypes
+
+Other built-in objects such as `Array`, `Date`, `Function` and others also keep methods in prototypes.
+
+For instance, when we create an array `[1, 2, 3]`, the default `new Array()` constructor is used internally. So `Array.prototype` becomes its prototype and provides methods. That's very memory-efficient.
+
+By specification, all of the built-in prototypes have `Object.prototype` on the top. That's why some people say that "everything inherits from objects".
+
+Here's the overall picture (for 3 built-ins to fit):
+
+
+
+Let's check the prototypes manually:
+
+```js run
+let arr = [1, 2, 3];
+
+// it inherits from Array.prototype?
+alert( arr.__proto__ === Array.prototype ); // true
+
+// then from Object.prototype?
+alert( arr.__proto__.__proto__ === Object.prototype ); // true
+
+// and null on the top.
+alert( arr.__proto__.__proto__.__proto__ ); // null
+```
+
+Some methods in prototypes may overlap, for instance, `Array.prototype` has its own `toString` that lists comma-delimited elements:
+
+```js run
+let arr = [1, 2, 3]
+alert(arr); // 1,2,3 <-- the result of Array.prototype.toString
+```
+
+As we've seen before, `Object.prototype` has `toString` as well, but `Array.prototype` is closer in the chain, so the array variant is used.
+
+
+
+
+
+In-browser tools like Chrome developer console also show inheritance (`console.dir` may need to be used for built-in objects):
+
+
+
+Other built-in objects also work the same way. Even functions -- they are objects of a built-in `Function` constructor, and their methods (`call`/`apply` and others) are taken from `Function.prototype`. Functions have their own `toString` too.
+
+```js run
+function f() {}
+
+alert(f.__proto__ == Function.prototype); // true
+alert(f.__proto__.__proto__ == Object.prototype); // true, inherit from objects
+```
+
+## Primitives
+
+The most intricate thing happens with strings, numbers and booleans.
+
+As we remember, they are not objects. But if we try to access their properties, temporary wrapper objects are created using built-in constructors `String`, `Number` and `Boolean`. They provide the methods and disappear.
+
+These objects are created invisibly to us and most engines optimize them out, but the specification describes it exactly this way. Methods of these objects also reside in prototypes, available as `String.prototype`, `Number.prototype` and `Boolean.prototype`.
+
+```warn header="Values `null` and `undefined` have no object wrappers"
+Special values `null` and `undefined` stand apart. They have no object wrappers, so methods and properties are not available for them. And there are no corresponding prototypes either.
+```
+
+## Changing native prototypes [#native-prototype-change]
+
+Native prototypes can be modified. For instance, if we add a method to `String.prototype`, it becomes available to all strings:
+
+```js run
+String.prototype.show = function() {
+ alert(this);
+};
+
+"BOOM!".show(); // BOOM!
+```
+
+During the process of development, we may have ideas for new built-in methods we'd like to have, and we may be tempted to add them to native prototypes. But that is generally a bad idea.
+
+```warn
+Prototypes are global, so it's easy to get a conflict. If two libraries add a method `String.prototype.show`, then one of them will be overwriting the method of the other.
+
+So, generally, modifying a native prototype is considered a bad idea.
+```
+
+**In modern programming, there is only one case where modifying native prototypes is approved. That's polyfilling.**
+
+Polyfilling is a term for making a substitute for a method that exists in the JavaScript specification, but is not yet supported by a particular JavaScript engine.
+
+We may then implement it manually and populate the built-in prototype with it.
+
+For instance:
+
+```js run
+if (!String.prototype.repeat) { // if there's no such method
+ // add it to the prototype
+
+ String.prototype.repeat = function(n) {
+ // repeat the string n times
+
+ // actually, the code should be a little bit more complex than that
+ // (the full algorithm is in the specification)
+ // but even an imperfect polyfill is often considered good enough
+ return new Array(n + 1).join(this);
+ };
+}
+
+alert( "La".repeat(3) ); // LaLaLa
+```
+
+
+## Borrowing from prototypes
+
+In the chapter we talked about method borrowing.
+
+That's when we take a method from one object and copy it into another.
+
+Some methods of native prototypes are often borrowed.
+
+For instance, if we're making an array-like object, we may want to copy some `Array` methods to it.
+
+E.g.
+
+```js run
+let obj = {
+ 0: "Hello",
+ 1: "world!",
+ length: 2,
+};
+
+*!*
+obj.join = Array.prototype.join;
+*/!*
+
+alert( obj.join(',') ); // Hello,world!
+```
+
+It works because the internal algorithm of the built-in `join` method only cares about the correct indexes and the `length` property. It doesn't check if the object is indeed an array. Many built-in methods are like that.
+
+Another possibility is to inherit by setting `obj.__proto__` to `Array.prototype`, so all `Array` methods are automatically available in `obj`.
+
+But that's impossible if `obj` already inherits from another object. Remember, we only can inherit from one object at a time.
+
+Borrowing methods is flexible, it allows to mix functionalities from different objects if needed.
+
+## Summary
+
+- All built-in objects follow the same pattern:
+ - The methods are stored in the prototype (`Array.prototype`, `Object.prototype`, `Date.prototype`, etc.)
+ - The object itself stores only the data (array items, object properties, the date)
+- Primitives also store methods in prototypes of wrapper objects: `Number.prototype`, `String.prototype` and `Boolean.prototype`. Only `undefined` and `null` do not have wrapper objects
+- Built-in prototypes can be modified or populated with new methods. But it's not recommended to change them. The only allowable case is probably when we add-in a new standard, but it's not yet supported by the JavaScript engine
diff --git a/1-js/07-object-oriented-programming/05-native-prototypes/console_dir_array.png b/1-js/08-prototypes/03-native-prototypes/console_dir_array.png
similarity index 100%
rename from 1-js/07-object-oriented-programming/05-native-prototypes/console_dir_array.png
rename to 1-js/08-prototypes/03-native-prototypes/console_dir_array.png
diff --git a/1-js/08-prototypes/03-native-prototypes/function-prototype-constructor.svg b/1-js/08-prototypes/03-native-prototypes/function-prototype-constructor.svg
new file mode 100644
index 0000000000..59d60b397a
--- /dev/null
+++ b/1-js/08-prototypes/03-native-prototypes/function-prototype-constructor.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/08-prototypes/03-native-prototypes/native-prototypes-array-tostring.svg b/1-js/08-prototypes/03-native-prototypes/native-prototypes-array-tostring.svg
new file mode 100644
index 0000000000..ebb4f32051
--- /dev/null
+++ b/1-js/08-prototypes/03-native-prototypes/native-prototypes-array-tostring.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/08-prototypes/03-native-prototypes/native-prototypes-classes.svg b/1-js/08-prototypes/03-native-prototypes/native-prototypes-classes.svg
new file mode 100644
index 0000000000..4d6129e0a0
--- /dev/null
+++ b/1-js/08-prototypes/03-native-prototypes/native-prototypes-classes.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/08-prototypes/03-native-prototypes/object-prototype-1.svg b/1-js/08-prototypes/03-native-prototypes/object-prototype-1.svg
new file mode 100644
index 0000000000..9630e68e27
--- /dev/null
+++ b/1-js/08-prototypes/03-native-prototypes/object-prototype-1.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/08-prototypes/03-native-prototypes/object-prototype-null.svg b/1-js/08-prototypes/03-native-prototypes/object-prototype-null.svg
new file mode 100644
index 0000000000..9ccb342299
--- /dev/null
+++ b/1-js/08-prototypes/03-native-prototypes/object-prototype-null.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/08-prototypes/03-native-prototypes/object-prototype.svg b/1-js/08-prototypes/03-native-prototypes/object-prototype.svg
new file mode 100644
index 0000000000..024dd30213
--- /dev/null
+++ b/1-js/08-prototypes/03-native-prototypes/object-prototype.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/08-prototypes/03-native-prototypes/rabbit-prototype-constructor.svg b/1-js/08-prototypes/03-native-prototypes/rabbit-prototype-constructor.svg
new file mode 100644
index 0000000000..54b3d79804
--- /dev/null
+++ b/1-js/08-prototypes/03-native-prototypes/rabbit-prototype-constructor.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/08-prototypes/04-prototype-methods/2-dictionary-tostring/solution.md b/1-js/08-prototypes/04-prototype-methods/2-dictionary-tostring/solution.md
new file mode 100644
index 0000000000..f3c9cf0e52
--- /dev/null
+++ b/1-js/08-prototypes/04-prototype-methods/2-dictionary-tostring/solution.md
@@ -0,0 +1,31 @@
+
+The method can take all enumerable keys using `Object.keys` and output their list.
+
+To make `toString` non-enumerable, let's define it using a property descriptor. The syntax of `Object.create` allows us to provide an object with property descriptors as the second argument.
+
+```js run
+*!*
+let dictionary = Object.create(null, {
+ toString: { // define toString property
+ value() { // the value is a function
+ return Object.keys(this).join();
+ }
+ }
+});
+*/!*
+
+dictionary.apple = "Apple";
+dictionary.__proto__ = "test";
+
+// apple and __proto__ is in the loop
+for(let key in dictionary) {
+ alert(key); // "apple", then "__proto__"
+}
+
+// comma-separated list of properties by toString
+alert(dictionary); // "apple,__proto__"
+```
+
+When we create a property using a descriptor, its flags are `false` by default. So in the code above, `dictionary.toString` is non-enumerable.
+
+See the chapter [](info:property-descriptors) for review.
diff --git a/1-js/07-object-oriented-programming/06-prototype-methods/2-dictionary-tostring/task.md b/1-js/08-prototypes/04-prototype-methods/2-dictionary-tostring/task.md
similarity index 100%
rename from 1-js/07-object-oriented-programming/06-prototype-methods/2-dictionary-tostring/task.md
rename to 1-js/08-prototypes/04-prototype-methods/2-dictionary-tostring/task.md
diff --git a/1-js/07-object-oriented-programming/06-prototype-methods/3-compare-calls/solution.md b/1-js/08-prototypes/04-prototype-methods/3-compare-calls/solution.md
similarity index 100%
rename from 1-js/07-object-oriented-programming/06-prototype-methods/3-compare-calls/solution.md
rename to 1-js/08-prototypes/04-prototype-methods/3-compare-calls/solution.md
diff --git a/1-js/08-prototypes/04-prototype-methods/3-compare-calls/task.md b/1-js/08-prototypes/04-prototype-methods/3-compare-calls/task.md
new file mode 100644
index 0000000000..09bb7f1ed8
--- /dev/null
+++ b/1-js/08-prototypes/04-prototype-methods/3-compare-calls/task.md
@@ -0,0 +1,27 @@
+importance: 5
+
+---
+
+# The difference between calls
+
+Let's create a new `rabbit` object:
+
+```js
+function Rabbit(name) {
+ this.name = name;
+}
+Rabbit.prototype.sayHi = function() {
+ alert(this.name);
+};
+
+let rabbit = new Rabbit("Rabbit");
+```
+
+These calls do the same thing or not?
+
+```js
+rabbit.sayHi();
+Rabbit.prototype.sayHi();
+Object.getPrototypeOf(rabbit).sayHi();
+rabbit.__proto__.sayHi();
+```
diff --git a/1-js/08-prototypes/04-prototype-methods/article.md b/1-js/08-prototypes/04-prototype-methods/article.md
new file mode 100644
index 0000000000..9c5f1eb3dd
--- /dev/null
+++ b/1-js/08-prototypes/04-prototype-methods/article.md
@@ -0,0 +1,223 @@
+
+# Prototype methods, objects without __proto__
+
+In the first chapter of this section, we mentioned that there are modern methods to setup a prototype.
+
+Setting or reading the prototype with `obj.__proto__` is considered outdated and somewhat deprecated (moved to the so-called "Annex B" of the JavaScript standard, meant for browsers only).
+
+The modern methods to get/set a prototype are:
+
+- [Object.getPrototypeOf(obj)](mdn:js/Object/getPrototypeOf) -- returns the `[[Prototype]]` of `obj`.
+- [Object.setPrototypeOf(obj, proto)](mdn:js/Object/setPrototypeOf) -- sets the `[[Prototype]]` of `obj` to `proto`.
+
+The only usage of `__proto__`, that's not frowned upon, is as a property when creating a new object: `{ __proto__: ... }`.
+
+Although, there's a special method for this too:
+
+- [Object.create(proto[, descriptors])](mdn:js/Object/create) -- creates an empty object with given `proto` as `[[Prototype]]` and optional property descriptors.
+
+For instance:
+
+```js run
+let animal = {
+ eats: true
+};
+
+// create a new object with animal as a prototype
+*!*
+let rabbit = Object.create(animal); // same as {__proto__: animal}
+*/!*
+
+alert(rabbit.eats); // true
+
+*!*
+alert(Object.getPrototypeOf(rabbit) === animal); // true
+*/!*
+
+*!*
+Object.setPrototypeOf(rabbit, {}); // change the prototype of rabbit to {}
+*/!*
+```
+
+The `Object.create` method is a bit more powerful, as it has an optional second argument: property descriptors.
+
+We can provide additional properties to the new object there, like this:
+
+```js run
+let animal = {
+ eats: true
+};
+
+let rabbit = Object.create(animal, {
+ jumps: {
+ value: true
+ }
+});
+
+alert(rabbit.jumps); // true
+```
+
+The descriptors are in the same format as described in the chapter .
+
+We can use `Object.create` to perform an object cloning more powerful than copying properties in `for..in`:
+
+```js
+let clone = Object.create(
+ Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj)
+);
+```
+
+This call makes a truly exact copy of `obj`, including all properties: enumerable and non-enumerable, data properties and setters/getters -- everything, and with the right `[[Prototype]]`.
+
+
+## Brief history
+
+There're so many ways to manage `[[Prototype]]`. How did that happen? Why?
+
+That's for historical reasons.
+
+The prototypal inheritance was in the language since its dawn, but the ways to manage it evolved over time.
+
+- The `prototype` property of a constructor function has worked since very ancient times. It's the oldest way to create objects with a given prototype.
+- Later, in the year 2012, `Object.create` appeared in the standard. It gave the ability to create objects with a given prototype, but did not provide the ability to get/set it. Some browsers implemented the non-standard `__proto__` accessor that allowed the user to get/set a prototype at any time, to give more flexibility to developers.
+- Later, in the year 2015, `Object.setPrototypeOf` and `Object.getPrototypeOf` were added to the standard, to perform the same functionality as `__proto__`. As `__proto__` was de-facto implemented everywhere, it was kind-of deprecated and made its way to the Annex B of the standard, that is: optional for non-browser environments.
+- Later, in the year 2022, it was officially allowed to use `__proto__` in object literals `{...}` (moved out of Annex B), but not as a getter/setter `obj.__proto__` (still in Annex B).
+
+Why was `__proto__` replaced by the functions `getPrototypeOf/setPrototypeOf`?
+
+Why was `__proto__` partially rehabilitated and its usage allowed in `{...}`, but not as a getter/setter?
+
+That's an interesting question, requiring us to understand why `__proto__` is bad.
+
+And soon we'll get the answer.
+
+```warn header="Don't change `[[Prototype]]` on existing objects if speed matters"
+Technically, we can get/set `[[Prototype]]` at any time. But usually we only set it once at the object creation time and don't modify it anymore: `rabbit` inherits from `animal`, and that is not going to change.
+
+And JavaScript engines are highly optimized for this. Changing a prototype "on-the-fly" with `Object.setPrototypeOf` or `obj.__proto__=` is a very slow operation as it breaks internal optimizations for object property access operations. So avoid it unless you know what you're doing, or JavaScript speed totally doesn't matter for you.
+```
+
+## "Very plain" objects [#very-plain]
+
+As we know, objects can be used as associative arrays to store key/value pairs.
+
+...But if we try to store *user-provided* keys in it (for instance, a user-entered dictionary), we can see an interesting glitch: all keys work fine except `"__proto__"`.
+
+Check out the example:
+
+```js run
+let obj = {};
+
+let key = prompt("What's the key?", "__proto__");
+obj[key] = "some value";
+
+alert(obj[key]); // [object Object], not "some value"!
+```
+
+Here, if the user types in `__proto__`, the assignment in line 4 is ignored!
+
+That could surely be surprising for a non-developer, but pretty understandable for us. The `__proto__` property is special: it must be either an object or `null`. A string can not become a prototype. That's why assigning a string to `__proto__` is ignored.
+
+But we didn't *intend* to implement such behavior, right? We want to store key/value pairs, and the key named `"__proto__"` was not properly saved. So that's a bug!
+
+Here the consequences are not terrible. But in other cases we may be storing objects instead of strings in `obj`, and then the prototype will indeed be changed. As a result, the execution will go wrong in totally unexpected ways.
+
+What's worse -- usually developers do not think about such possibility at all. That makes such bugs hard to notice and even turn them into vulnerabilities, especially when JavaScript is used on server-side.
+
+Unexpected things also may happen when assigning to `obj.toString`, as it's a built-in object method.
+
+How can we avoid this problem?
+
+First, we can just switch to using `Map` for storage instead of plain objects, then everything's fine:
+
+```js run
+let map = new Map();
+
+let key = prompt("What's the key?", "__proto__");
+map.set(key, "some value");
+
+alert(map.get(key)); // "some value" (as intended)
+```
+
+...But `Object` syntax is often more appealing, as it's more concise.
+
+Fortunately, we *can* use objects, because language creators gave thought to that problem long ago.
+
+As we know, `__proto__` is not a property of an object, but an accessor property of `Object.prototype`:
+
+
+
+So, if `obj.__proto__` is read or set, the corresponding getter/setter is called from its prototype, and it gets/sets `[[Prototype]]`.
+
+As it was said in the beginning of this tutorial section: `__proto__` is a way to access `[[Prototype]]`, it is not `[[Prototype]]` itself.
+
+Now, if we intend to use an object as an associative array and be free of such problems, we can do it with a little trick:
+
+```js run
+*!*
+let obj = Object.create(null);
+// or: obj = { __proto__: null }
+*/!*
+
+let key = prompt("What's the key?", "__proto__");
+obj[key] = "some value";
+
+alert(obj[key]); // "some value"
+```
+
+`Object.create(null)` creates an empty object without a prototype (`[[Prototype]]` is `null`):
+
+
+
+So, there is no inherited getter/setter for `__proto__`. Now it is processed as a regular data property, so the example above works right.
+
+We can call such objects "very plain" or "pure dictionary" objects, because they are even simpler than the regular plain object `{...}`.
+
+A downside is that such objects lack any built-in object methods, e.g. `toString`:
+
+```js run
+*!*
+let obj = Object.create(null);
+*/!*
+
+alert(obj); // Error (no toString)
+```
+
+...But that's usually fine for associative arrays.
+
+Note that most object-related methods are `Object.something(...)`, like `Object.keys(obj)` -- they are not in the prototype, so they will keep working on such objects:
+
+
+```js run
+let chineseDictionary = Object.create(null);
+chineseDictionary.hello = "你好";
+chineseDictionary.bye = "再见";
+
+alert(Object.keys(chineseDictionary)); // hello,bye
+```
+
+## Summary
+
+- To create an object with the given prototype, use:
+
+ - literal syntax: `{ __proto__: ... }`, allows to specify multiple properties
+ - or [Object.create(proto[, descriptors])](mdn:js/Object/create), allows to specify property descriptors.
+
+ The `Object.create` provides an easy way to shallow-copy an object with all descriptors:
+
+ ```js
+ let clone = Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj));
+ ```
+
+- Modern methods to get/set the prototype are:
+
+ - [Object.getPrototypeOf(obj)](mdn:js/Object/getPrototypeOf) -- returns the `[[Prototype]]` of `obj` (same as `__proto__` getter).
+ - [Object.setPrototypeOf(obj, proto)](mdn:js/Object/setPrototypeOf) -- sets the `[[Prototype]]` of `obj` to `proto` (same as `__proto__` setter).
+
+- Getting/setting the prototype using the built-in `__proto__` getter/setter isn't recommended, it's now in the Annex B of the specification.
+
+- We also covered prototype-less objects, created with `Object.create(null)` or `{__proto__: null}`.
+
+ These objects are used as dictionaries, to store any (possibly user-generated) keys.
+
+ Normally, objects inherit built-in methods and `__proto__` getter/setter from `Object.prototype`, making corresponding keys "occupied" and potentially causing side effects. With `null` prototype, objects are truly empty.
diff --git a/1-js/08-prototypes/04-prototype-methods/object-prototype-2.svg b/1-js/08-prototypes/04-prototype-methods/object-prototype-2.svg
new file mode 100644
index 0000000000..cf4d3023f8
--- /dev/null
+++ b/1-js/08-prototypes/04-prototype-methods/object-prototype-2.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/08-prototypes/04-prototype-methods/object-prototype-null.svg b/1-js/08-prototypes/04-prototype-methods/object-prototype-null.svg
new file mode 100644
index 0000000000..9ccb342299
--- /dev/null
+++ b/1-js/08-prototypes/04-prototype-methods/object-prototype-null.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/08-prototypes/index.md b/1-js/08-prototypes/index.md
new file mode 100644
index 0000000000..8554a0e30b
--- /dev/null
+++ b/1-js/08-prototypes/index.md
@@ -0,0 +1 @@
+# Prototypes, inheritance
diff --git a/1-js/09-classes/01-class/1-rewrite-to-class/_js.view/solution.js b/1-js/09-classes/01-class/1-rewrite-to-class/_js.view/solution.js
new file mode 100644
index 0000000000..0b31cf334e
--- /dev/null
+++ b/1-js/09-classes/01-class/1-rewrite-to-class/_js.view/solution.js
@@ -0,0 +1,38 @@
+class Clock {
+ constructor({ template }) {
+ this.template = template;
+ }
+
+ render() {
+ let date = new Date();
+
+ let hours = date.getHours();
+ if (hours < 10) hours = '0' + hours;
+
+ let mins = date.getMinutes();
+ if (mins < 10) mins = '0' + mins;
+
+ let secs = date.getSeconds();
+ if (secs < 10) secs = '0' + secs;
+
+ let output = this.template
+ .replace('h', hours)
+ .replace('m', mins)
+ .replace('s', secs);
+
+ console.log(output);
+ }
+
+ stop() {
+ clearInterval(this.timer);
+ }
+
+ start() {
+ this.render();
+ this.timer = setInterval(() => this.render(), 1000);
+ }
+}
+
+
+let clock = new Clock({template: 'h:m:s'});
+clock.start();
diff --git a/1-js/09-classes/01-class/1-rewrite-to-class/_js.view/source.js b/1-js/09-classes/01-class/1-rewrite-to-class/_js.view/source.js
new file mode 100644
index 0000000000..f1749c8ba5
--- /dev/null
+++ b/1-js/09-classes/01-class/1-rewrite-to-class/_js.view/source.js
@@ -0,0 +1,37 @@
+function Clock({ template }) {
+
+ let timer;
+
+ function render() {
+ let date = new Date();
+
+ let hours = date.getHours();
+ if (hours < 10) hours = '0' + hours;
+
+ let mins = date.getMinutes();
+ if (mins < 10) mins = '0' + mins;
+
+ let secs = date.getSeconds();
+ if (secs < 10) secs = '0' + secs;
+
+ let output = template
+ .replace('h', hours)
+ .replace('m', mins)
+ .replace('s', secs);
+
+ console.log(output);
+ }
+
+ this.stop = function() {
+ clearInterval(timer);
+ };
+
+ this.start = function() {
+ render();
+ timer = setInterval(render, 1000);
+ };
+
+}
+
+let clock = new Clock({template: 'h:m:s'});
+clock.start();
diff --git a/1-js/07-object-oriented-programming/10-class-inheritance/2-clock-class-extended/solution.md b/1-js/09-classes/01-class/1-rewrite-to-class/solution.md
similarity index 100%
rename from 1-js/07-object-oriented-programming/10-class-inheritance/2-clock-class-extended/solution.md
rename to 1-js/09-classes/01-class/1-rewrite-to-class/solution.md
diff --git a/1-js/09-classes/01-class/1-rewrite-to-class/task.md b/1-js/09-classes/01-class/1-rewrite-to-class/task.md
new file mode 100644
index 0000000000..4477de6799
--- /dev/null
+++ b/1-js/09-classes/01-class/1-rewrite-to-class/task.md
@@ -0,0 +1,9 @@
+importance: 5
+
+---
+
+# Rewrite to class
+
+The `Clock` class (see the sandbox) is written in functional style. Rewrite it in the "class" syntax.
+
+P.S. The clock ticks in the console, open it to see.
diff --git a/1-js/09-classes/01-class/article.md b/1-js/09-classes/01-class/article.md
new file mode 100644
index 0000000000..135d24929b
--- /dev/null
+++ b/1-js/09-classes/01-class/article.md
@@ -0,0 +1,428 @@
+
+# Class basic syntax
+
+```quote author="Wikipedia"
+In object-oriented programming, a *class* is an extensible program-code-template for creating objects, providing initial values for state (member variables) and implementations of behavior (member functions or methods).
+```
+
+In practice, we often need to create many objects of the same kind, like users, or goods or whatever.
+
+As we already know from the chapter , `new function` can help with that.
+
+But in the modern JavaScript, there's a more advanced "class" construct, that introduces great new features which are useful for object-oriented programming.
+
+## The "class" syntax
+
+The basic syntax is:
+```js
+class MyClass {
+ // class methods
+ constructor() { ... }
+ method1() { ... }
+ method2() { ... }
+ method3() { ... }
+ ...
+}
+```
+
+Then use `new MyClass()` to create a new object with all the listed methods.
+
+The `constructor()` method is called automatically by `new`, so we can initialize the object there.
+
+For example:
+
+```js run
+class User {
+
+ constructor(name) {
+ this.name = name;
+ }
+
+ sayHi() {
+ alert(this.name);
+ }
+
+}
+
+// Usage:
+let user = new User("John");
+user.sayHi();
+```
+
+When `new User("John")` is called:
+1. A new object is created.
+2. The `constructor` runs with the given argument and assigns it to `this.name`.
+
+...Then we can call object methods, such as `user.sayHi()`.
+
+
+```warn header="No comma between class methods"
+A common pitfall for novice developers is to put a comma between class methods, which would result in a syntax error.
+
+The notation here is not to be confused with object literals. Within the class, no commas are required.
+```
+
+## What is a class?
+
+So, what exactly is a `class`? That's not an entirely new language-level entity, as one might think.
+
+Let's unveil any magic and see what a class really is. That'll help in understanding many complex aspects.
+
+In JavaScript, a class is a kind of function.
+
+Here, take a look:
+
+```js run
+class User {
+ constructor(name) { this.name = name; }
+ sayHi() { alert(this.name); }
+}
+
+// proof: User is a function
+*!*
+alert(typeof User); // function
+*/!*
+```
+
+What `class User {...}` construct really does is:
+
+1. Creates a function named `User`, that becomes the result of the class declaration. The function code is taken from the `constructor` method (assumed empty if we don't write such method).
+2. Stores class methods, such as `sayHi`, in `User.prototype`.
+
+After `new User` object is created, when we call its method, it's taken from the prototype, just as described in the chapter . So the object has access to class methods.
+
+We can illustrate the result of `class User` declaration as:
+
+
+
+Here's the code to introspect it:
+
+```js run
+class User {
+ constructor(name) { this.name = name; }
+ sayHi() { alert(this.name); }
+}
+
+// class is a function
+alert(typeof User); // function
+
+// ...or, more precisely, the constructor method
+alert(User === User.prototype.constructor); // true
+
+// The methods are in User.prototype, e.g:
+alert(User.prototype.sayHi); // the code of the sayHi method
+
+// there are exactly two methods in the prototype
+alert(Object.getOwnPropertyNames(User.prototype)); // constructor, sayHi
+```
+
+## Not just a syntactic sugar
+
+Sometimes people say that `class` is a "syntactic sugar" (syntax that is designed to make things easier to read, but doesn't introduce anything new), because we could actually declare the same thing without using the `class` keyword at all:
+
+```js run
+// rewriting class User in pure functions
+
+// 1. Create constructor function
+function User(name) {
+ this.name = name;
+}
+// a function prototype has "constructor" property by default,
+// so we don't need to create it
+
+// 2. Add the method to prototype
+User.prototype.sayHi = function() {
+ alert(this.name);
+};
+
+// Usage:
+let user = new User("John");
+user.sayHi();
+```
+
+The result of this definition is about the same. So, there are indeed reasons why `class` can be considered a syntactic sugar to define a constructor together with its prototype methods.
+
+Still, there are important differences.
+
+1. First, a function created by `class` is labelled by a special internal property `[[IsClassConstructor]]: true`. So it's not entirely the same as creating it manually.
+
+ The language checks for that property in a variety of places. For example, unlike a regular function, it must be called with `new`:
+
+ ```js run
+ class User {
+ constructor() {}
+ }
+
+ alert(typeof User); // function
+ User(); // Error: Class constructor User cannot be invoked without 'new'
+ ```
+
+ Also, a string representation of a class constructor in most JavaScript engines starts with the "class..."
+
+ ```js run
+ class User {
+ constructor() {}
+ }
+
+ alert(User); // class User { ... }
+ ```
+ There are other differences, we'll see them soon.
+
+2. Class methods are non-enumerable.
+ A class definition sets `enumerable` flag to `false` for all methods in the `"prototype"`.
+
+ That's good, because if we `for..in` over an object, we usually don't want its class methods.
+
+3. Classes always `use strict`.
+ All code inside the class construct is automatically in strict mode.
+
+Besides, `class` syntax brings many other features that we'll explore later.
+
+## Class Expression
+
+Just like functions, classes can be defined inside another expression, passed around, returned, assigned, etc.
+
+Here's an example of a class expression:
+
+```js
+let User = class {
+ sayHi() {
+ alert("Hello");
+ }
+};
+```
+
+Similar to Named Function Expressions, class expressions may have a name.
+
+If a class expression has a name, it's visible inside the class only:
+
+```js run
+// "Named Class Expression"
+// (no such term in the spec, but that's similar to Named Function Expression)
+let User = class *!*MyClass*/!* {
+ sayHi() {
+ alert(MyClass); // MyClass name is visible only inside the class
+ }
+};
+
+new User().sayHi(); // works, shows MyClass definition
+
+alert(MyClass); // error, MyClass name isn't visible outside of the class
+```
+
+We can even make classes dynamically "on-demand", like this:
+
+```js run
+function makeClass(phrase) {
+ // declare a class and return it
+ return class {
+ sayHi() {
+ alert(phrase);
+ }
+ };
+}
+
+// Create a new class
+let User = makeClass("Hello");
+
+new User().sayHi(); // Hello
+```
+
+
+## Getters/setters
+
+Just like literal objects, classes may include getters/setters, computed properties etc.
+
+Here's an example for `user.name` implemented using `get/set`:
+
+```js run
+class User {
+
+ constructor(name) {
+ // invokes the setter
+ this.name = name;
+ }
+
+*!*
+ get name() {
+*/!*
+ return this._name;
+ }
+
+*!*
+ set name(value) {
+*/!*
+ if (value.length < 4) {
+ alert("Name is too short.");
+ return;
+ }
+ this._name = value;
+ }
+
+}
+
+let user = new User("John");
+alert(user.name); // John
+
+user = new User(""); // Name is too short.
+```
+
+Technically, such class declaration works by creating getters and setters in `User.prototype`.
+
+## Computed names [...]
+
+Here's an example with a computed method name using brackets `[...]`:
+
+```js run
+class User {
+
+*!*
+ ['say' + 'Hi']() {
+*/!*
+ alert("Hello");
+ }
+
+}
+
+new User().sayHi();
+```
+
+Such features are easy to remember, as they resemble that of literal objects.
+
+## Class fields
+
+```warn header="Old browsers may need a polyfill"
+Class fields are a recent addition to the language.
+```
+
+Previously, our classes only had methods.
+
+"Class fields" is a syntax that allows to add any properties.
+
+For instance, let's add `name` property to `class User`:
+
+```js run
+class User {
+*!*
+ name = "John";
+*/!*
+
+ sayHi() {
+ alert(`Hello, ${this.name}!`);
+ }
+}
+
+new User().sayHi(); // Hello, John!
+```
+
+So, we just write " = " in the declaration, and that's it.
+
+The important difference of class fields is that they are set on individual objects, not `User.prototype`:
+
+```js run
+class User {
+*!*
+ name = "John";
+*/!*
+}
+
+let user = new User();
+alert(user.name); // John
+alert(User.prototype.name); // undefined
+```
+
+We can also assign values using more complex expressions and function calls:
+
+```js run
+class User {
+*!*
+ name = prompt("Name, please?", "John");
+*/!*
+}
+
+let user = new User();
+alert(user.name); // John
+```
+
+
+### Making bound methods with class fields
+
+As demonstrated in the chapter functions in JavaScript have a dynamic `this`. It depends on the context of the call.
+
+So if an object method is passed around and called in another context, `this` won't be a reference to its object any more.
+
+For instance, this code will show `undefined`:
+
+```js run
+class Button {
+ constructor(value) {
+ this.value = value;
+ }
+
+ click() {
+ alert(this.value);
+ }
+}
+
+let button = new Button("hello");
+
+*!*
+setTimeout(button.click, 1000); // undefined
+*/!*
+```
+
+The problem is called "losing `this`".
+
+There are two approaches to fixing it, as discussed in the chapter :
+
+1. Pass a wrapper-function, such as `setTimeout(() => button.click(), 1000)`.
+2. Bind the method to object, e.g. in the constructor.
+
+Class fields provide another, quite elegant syntax:
+
+```js run
+class Button {
+ constructor(value) {
+ this.value = value;
+ }
+*!*
+ click = () => {
+ alert(this.value);
+ }
+*/!*
+}
+
+let button = new Button("hello");
+
+setTimeout(button.click, 1000); // hello
+```
+
+The class field `click = () => {...}` is created on a per-object basis, there's a separate function for each `Button` object, with `this` inside it referencing that object. We can pass `button.click` around anywhere, and the value of `this` will always be correct.
+
+That's especially useful in browser environment, for event listeners.
+
+## Summary
+
+The basic class syntax looks like this:
+
+```js
+class MyClass {
+ prop = value; // property
+
+ constructor(...) { // constructor
+ // ...
+ }
+
+ method(...) {} // method
+
+ get something(...) {} // getter method
+ set something(...) {} // setter method
+
+ [Symbol.iterator]() {} // method with computed name (symbol here)
+ // ...
+}
+```
+
+`MyClass` is technically a function (the one that we provide as `constructor`), while methods, getters and setters are written to `MyClass.prototype`.
+
+In the next chapters we'll learn more about classes, including inheritance and other features.
diff --git a/1-js/09-classes/01-class/class-user.svg b/1-js/09-classes/01-class/class-user.svg
new file mode 100644
index 0000000000..418d71d187
--- /dev/null
+++ b/1-js/09-classes/01-class/class-user.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/07-object-oriented-programming/10-class-inheritance/1-class-constructor-error/solution.md b/1-js/09-classes/02-class-inheritance/1-class-constructor-error/solution.md
similarity index 100%
rename from 1-js/07-object-oriented-programming/10-class-inheritance/1-class-constructor-error/solution.md
rename to 1-js/09-classes/02-class-inheritance/1-class-constructor-error/solution.md
diff --git a/1-js/07-object-oriented-programming/10-class-inheritance/1-class-constructor-error/task.md b/1-js/09-classes/02-class-inheritance/1-class-constructor-error/task.md
similarity index 100%
rename from 1-js/07-object-oriented-programming/10-class-inheritance/1-class-constructor-error/task.md
rename to 1-js/09-classes/02-class-inheritance/1-class-constructor-error/task.md
diff --git a/1-js/09-classes/02-class-inheritance/2-clock-class-extended/solution.md b/1-js/09-classes/02-class-inheritance/2-clock-class-extended/solution.md
new file mode 100644
index 0000000000..dcb4ffe59a
--- /dev/null
+++ b/1-js/09-classes/02-class-inheritance/2-clock-class-extended/solution.md
@@ -0,0 +1 @@
+[js src="http://github.com/solution.view/extended-clock.js"]
diff --git a/1-js/09-classes/02-class-inheritance/2-clock-class-extended/solution.view/clock.js b/1-js/09-classes/02-class-inheritance/2-clock-class-extended/solution.view/clock.js
new file mode 100644
index 0000000000..d701c0caeb
--- /dev/null
+++ b/1-js/09-classes/02-class-inheritance/2-clock-class-extended/solution.view/clock.js
@@ -0,0 +1,34 @@
+class Clock {
+ constructor({ template }) {
+ this.template = template;
+ }
+
+ render() {
+ let date = new Date();
+
+ let hours = date.getHours();
+ if (hours < 10) hours = '0' + hours;
+
+ let mins = date.getMinutes();
+ if (mins < 10) mins = '0' + mins;
+
+ let secs = date.getSeconds();
+ if (secs < 10) secs = '0' + secs;
+
+ let output = this.template
+ .replace('h', hours)
+ .replace('m', mins)
+ .replace('s', secs);
+
+ console.log(output);
+ }
+
+ stop() {
+ clearInterval(this.timer);
+ }
+
+ start() {
+ this.render();
+ this.timer = setInterval(() => this.render(), 1000);
+ }
+}
diff --git a/1-js/09-classes/02-class-inheritance/2-clock-class-extended/solution.view/extended-clock.js b/1-js/09-classes/02-class-inheritance/2-clock-class-extended/solution.view/extended-clock.js
new file mode 100644
index 0000000000..be2053cfcf
--- /dev/null
+++ b/1-js/09-classes/02-class-inheritance/2-clock-class-extended/solution.view/extended-clock.js
@@ -0,0 +1,12 @@
+class ExtendedClock extends Clock {
+ constructor(options) {
+ super(options);
+ let { precision = 1000 } = options;
+ this.precision = precision;
+ }
+
+ start() {
+ this.render();
+ this.timer = setInterval(() => this.render(), this.precision);
+ }
+};
diff --git a/1-js/09-classes/02-class-inheritance/2-clock-class-extended/solution.view/index.html b/1-js/09-classes/02-class-inheritance/2-clock-class-extended/solution.view/index.html
new file mode 100644
index 0000000000..f76a436238
--- /dev/null
+++ b/1-js/09-classes/02-class-inheritance/2-clock-class-extended/solution.view/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/1-js/09-classes/02-class-inheritance/2-clock-class-extended/source.view/clock.js b/1-js/09-classes/02-class-inheritance/2-clock-class-extended/source.view/clock.js
new file mode 100644
index 0000000000..d701c0caeb
--- /dev/null
+++ b/1-js/09-classes/02-class-inheritance/2-clock-class-extended/source.view/clock.js
@@ -0,0 +1,34 @@
+class Clock {
+ constructor({ template }) {
+ this.template = template;
+ }
+
+ render() {
+ let date = new Date();
+
+ let hours = date.getHours();
+ if (hours < 10) hours = '0' + hours;
+
+ let mins = date.getMinutes();
+ if (mins < 10) mins = '0' + mins;
+
+ let secs = date.getSeconds();
+ if (secs < 10) secs = '0' + secs;
+
+ let output = this.template
+ .replace('h', hours)
+ .replace('m', mins)
+ .replace('s', secs);
+
+ console.log(output);
+ }
+
+ stop() {
+ clearInterval(this.timer);
+ }
+
+ start() {
+ this.render();
+ this.timer = setInterval(() => this.render(), 1000);
+ }
+}
diff --git a/1-js/09-classes/02-class-inheritance/2-clock-class-extended/source.view/index.html b/1-js/09-classes/02-class-inheritance/2-clock-class-extended/source.view/index.html
new file mode 100644
index 0000000000..c0609858b8
--- /dev/null
+++ b/1-js/09-classes/02-class-inheritance/2-clock-class-extended/source.view/index.html
@@ -0,0 +1,21 @@
+
+
+
diff --git a/1-js/09-classes/02-class-inheritance/2-clock-class-extended/task.md b/1-js/09-classes/02-class-inheritance/2-clock-class-extended/task.md
new file mode 100644
index 0000000000..bbc2c6a43c
--- /dev/null
+++ b/1-js/09-classes/02-class-inheritance/2-clock-class-extended/task.md
@@ -0,0 +1,15 @@
+importance: 5
+
+---
+
+# Extended clock
+
+We've got a `Clock` class. As of now, it prints the time every second.
+
+
+[js src="http://github.com/source.view/clock.js"]
+
+Create a new class `ExtendedClock` that inherits from `Clock` and adds the parameter `precision` -- the number of `ms` between "ticks". Should be `1000` (1 second) by default.
+
+- Your code should be in the file `extended-clock.js`
+- Don't modify the original `clock.js`. Extend it.
diff --git a/1-js/09-classes/02-class-inheritance/animal-rabbit-extends.svg b/1-js/09-classes/02-class-inheritance/animal-rabbit-extends.svg
new file mode 100644
index 0000000000..63b5a18a19
--- /dev/null
+++ b/1-js/09-classes/02-class-inheritance/animal-rabbit-extends.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/09-classes/02-class-inheritance/article.md b/1-js/09-classes/02-class-inheritance/article.md
new file mode 100644
index 0000000000..464042d823
--- /dev/null
+++ b/1-js/09-classes/02-class-inheritance/article.md
@@ -0,0 +1,627 @@
+
+# Class inheritance
+
+Class inheritance is a way for one class to extend another class.
+
+So we can create new functionality on top of the existing.
+
+## The "extends" keyword
+
+Let's say we have class `Animal`:
+
+```js
+class Animal {
+ constructor(name) {
+ this.speed = 0;
+ this.name = name;
+ }
+ run(speed) {
+ this.speed = speed;
+ alert(`${this.name} runs with speed ${this.speed}.`);
+ }
+ stop() {
+ this.speed = 0;
+ alert(`${this.name} stands still.`);
+ }
+}
+
+let animal = new Animal("My animal");
+```
+
+Here's how we can represent `animal` object and `Animal` class graphically:
+
+
+
+...And we would like to create another `class Rabbit`.
+
+As rabbits are animals, `Rabbit` class should be based on `Animal`, have access to animal methods, so that rabbits can do what "generic" animals can do.
+
+The syntax to extend another class is: `class Child extends Parent`.
+
+Let's create `class Rabbit` that inherits from `Animal`:
+
+```js
+*!*
+class Rabbit extends Animal {
+*/!*
+ hide() {
+ alert(`${this.name} hides!`);
+ }
+}
+
+let rabbit = new Rabbit("White Rabbit");
+
+rabbit.run(5); // White Rabbit runs with speed 5.
+rabbit.hide(); // White Rabbit hides!
+```
+
+Object of `Rabbit` class have access both to `Rabbit` methods, such as `rabbit.hide()`, and also to `Animal` methods, such as `rabbit.run()`.
+
+Internally, `extends` keyword works using the good old prototype mechanics. It sets `Rabbit.prototype.[[Prototype]]` to `Animal.prototype`. So, if a method is not found in `Rabbit.prototype`, JavaScript takes it from `Animal.prototype`.
+
+
+
+For instance, to find `rabbit.run` method, the engine checks (bottom-up on the picture):
+1. The `rabbit` object (has no `run`).
+2. Its prototype, that is `Rabbit.prototype` (has `hide`, but not `run`).
+3. Its prototype, that is (due to `extends`) `Animal.prototype`, that finally has the `run` method.
+
+As we can recall from the chapter , JavaScript itself uses prototypal inheritance for built-in objects. E.g. `Date.prototype.[[Prototype]]` is `Object.prototype`. That's why dates have access to generic object methods.
+
+````smart header="Any expression is allowed after `extends`"
+Class syntax allows to specify not just a class, but any expression after `extends`.
+
+For instance, a function call that generates the parent class:
+
+```js run
+function f(phrase) {
+ return class {
+ sayHi() { alert(phrase); }
+ };
+}
+
+*!*
+class User extends f("Hello") {}
+*/!*
+
+new User().sayHi(); // Hello
+```
+Here `class User` inherits from the result of `f("Hello")`.
+
+That may be useful for advanced programming patterns when we use functions to generate classes depending on many conditions and can inherit from them.
+````
+
+## Overriding a method
+
+Now let's move forward and override a method. By default, all methods that are not specified in `class Rabbit` are taken directly "as is" from `class Animal`.
+
+But if we specify our own method in `Rabbit`, such as `stop()` then it will be used instead:
+
+```js
+class Rabbit extends Animal {
+ stop() {
+ // ...now this will be used for rabbit.stop()
+ // instead of stop() from class Animal
+ }
+}
+```
+
+Usually, however, we don't want to totally replace a parent method, but rather to build on top of it to tweak or extend its functionality. We do something in our method, but call the parent method before/after it or in the process.
+
+Classes provide `"super"` keyword for that.
+
+- `super.method(...)` to call a parent method.
+- `super(...)` to call a parent constructor (inside our constructor only).
+
+For instance, let our rabbit autohide when stopped:
+
+```js run
+class Animal {
+
+ constructor(name) {
+ this.speed = 0;
+ this.name = name;
+ }
+
+ run(speed) {
+ this.speed = speed;
+ alert(`${this.name} runs with speed ${this.speed}.`);
+ }
+
+ stop() {
+ this.speed = 0;
+ alert(`${this.name} stands still.`);
+ }
+
+}
+
+class Rabbit extends Animal {
+ hide() {
+ alert(`${this.name} hides!`);
+ }
+
+*!*
+ stop() {
+ super.stop(); // call parent stop
+ this.hide(); // and then hide
+ }
+*/!*
+}
+
+let rabbit = new Rabbit("White Rabbit");
+
+rabbit.run(5); // White Rabbit runs with speed 5.
+rabbit.stop(); // White Rabbit stands still. White Rabbit hides!
+```
+
+Now `Rabbit` has the `stop` method that calls the parent `super.stop()` in the process.
+
+````smart header="Arrow functions have no `super`"
+As was mentioned in the chapter , arrow functions do not have `super`.
+
+If accessed, it's taken from the outer function. For instance:
+
+```js
+class Rabbit extends Animal {
+ stop() {
+ setTimeout(() => super.stop(), 1000); // call parent stop after 1sec
+ }
+}
+```
+
+The `super` in the arrow function is the same as in `stop()`, so it works as intended. If we specified a "regular" function here, there would be an error:
+
+```js
+// Unexpected super
+setTimeout(function() { super.stop() }, 1000);
+```
+````
+
+## Overriding constructor
+
+With constructors it gets a little bit tricky.
+
+Until now, `Rabbit` did not have its own `constructor`.
+
+According to the [specification](https://tc39.github.io/ecma262/#sec-runtime-semantics-classdefinitionevaluation), if a class extends another class and has no `constructor`, then the following "empty" `constructor` is generated:
+
+```js
+class Rabbit extends Animal {
+ // generated for extending classes without own constructors
+*!*
+ constructor(...args) {
+ super(...args);
+ }
+*/!*
+}
+```
+
+As we can see, it basically calls the parent `constructor` passing it all the arguments. That happens if we don't write a constructor of our own.
+
+Now let's add a custom constructor to `Rabbit`. It will specify the `earLength` in addition to `name`:
+
+```js run
+class Animal {
+ constructor(name) {
+ this.speed = 0;
+ this.name = name;
+ }
+ // ...
+}
+
+class Rabbit extends Animal {
+
+*!*
+ constructor(name, earLength) {
+ this.speed = 0;
+ this.name = name;
+ this.earLength = earLength;
+ }
+*/!*
+
+ // ...
+}
+
+*!*
+// Doesn't work!
+let rabbit = new Rabbit("White Rabbit", 10); // Error: this is not defined.
+*/!*
+```
+
+Whoops! We've got an error. Now we can't create rabbits. What went wrong?
+
+The short answer is:
+
+- **Constructors in inheriting classes must call `super(...)`, and (!) do it before using `this`.**
+
+...But why? What's going on here? Indeed, the requirement seems strange.
+
+Of course, there's an explanation. Let's get into details, so you'll really understand what's going on.
+
+In JavaScript, there's a distinction between a constructor function of an inheriting class (so-called "derived constructor") and other functions. A derived constructor has a special internal property `[[ConstructorKind]]:"derived"`. That's a special internal label.
+
+That label affects its behavior with `new`.
+
+- When a regular function is executed with `new`, it creates an empty object and assigns it to `this`.
+- But when a derived constructor runs, it doesn't do this. It expects the parent constructor to do this job.
+
+So a derived constructor must call `super` in order to execute its parent (base) constructor, otherwise the object for `this` won't be created. And we'll get an error.
+
+For the `Rabbit` constructor to work, it needs to call `super()` before using `this`, like here:
+
+```js run
+class Animal {
+
+ constructor(name) {
+ this.speed = 0;
+ this.name = name;
+ }
+
+ // ...
+}
+
+class Rabbit extends Animal {
+
+ constructor(name, earLength) {
+*!*
+ super(name);
+*/!*
+ this.earLength = earLength;
+ }
+
+ // ...
+}
+
+*!*
+// now fine
+let rabbit = new Rabbit("White Rabbit", 10);
+alert(rabbit.name); // White Rabbit
+alert(rabbit.earLength); // 10
+*/!*
+```
+
+### Overriding class fields: a tricky note
+
+```warn header="Advanced note"
+This note assumes you have a certain experience with classes, maybe in other programming languages.
+
+It provides better insight into the language and also explains the behavior that might be a source of bugs (but not very often).
+
+If you find it difficult to understand, just go on, continue reading, then return to it some time later.
+```
+
+We can override not only methods, but also class fields.
+
+Although, there's a tricky behavior when we access an overridden field in parent constructor, quite different from most other programming languages.
+
+Consider this example:
+
+```js run
+class Animal {
+ name = 'animal';
+
+ constructor() {
+ alert(this.name); // (*)
+ }
+}
+
+class Rabbit extends Animal {
+ name = 'rabbit';
+}
+
+new Animal(); // animal
+*!*
+new Rabbit(); // animal
+*/!*
+```
+
+Here, class `Rabbit` extends `Animal` and overrides the `name` field with its own value.
+
+There's no own constructor in `Rabbit`, so `Animal` constructor is called.
+
+What's interesting is that in both cases: `new Animal()` and `new Rabbit()`, the `alert` in the line `(*)` shows `animal`.
+
+**In other words, the parent constructor always uses its own field value, not the overridden one.**
+
+What's odd about it?
+
+If it's not clear yet, please compare with methods.
+
+Here's the same code, but instead of `this.name` field we call `this.showName()` method:
+
+```js run
+class Animal {
+ showName() { // instead of this.name = 'animal'
+ alert('animal');
+ }
+
+ constructor() {
+ this.showName(); // instead of alert(this.name);
+ }
+}
+
+class Rabbit extends Animal {
+ showName() {
+ alert('rabbit');
+ }
+}
+
+new Animal(); // animal
+*!*
+new Rabbit(); // rabbit
+*/!*
+```
+
+Please note: now the output is different.
+
+And that's what we naturally expect. When the parent constructor is called in the derived class, it uses the overridden method.
+
+...But for class fields it's not so. As said, the parent constructor always uses the parent field.
+
+Why is there a difference?
+
+Well, the reason is the field initialization order. The class field is initialized:
+- Before constructor for the base class (that doesn't extend anything),
+- Immediately after `super()` for the derived class.
+
+In our case, `Rabbit` is the derived class. There's no `constructor()` in it. As said previously, that's the same as if there was an empty constructor with only `super(...args)`.
+
+So, `new Rabbit()` calls `super()`, thus executing the parent constructor, and (per the rule for derived classes) only after that its class fields are initialized. At the time of the parent constructor execution, there are no `Rabbit` class fields yet, that's why `Animal` fields are used.
+
+This subtle difference between fields and methods is specific to JavaScript.
+
+Luckily, this behavior only reveals itself if an overridden field is used in the parent constructor. Then it may be difficult to understand what's going on, so we're explaining it here.
+
+If it becomes a problem, one can fix it by using methods or getters/setters instead of fields.
+
+## Super: internals, [[HomeObject]]
+
+```warn header="Advanced information"
+If you're reading the tutorial for the first time - this section may be skipped.
+
+It's about the internal mechanisms behind inheritance and `super`.
+```
+
+Let's get a little deeper under the hood of `super`. We'll see some interesting things along the way.
+
+First to say, from all that we've learned till now, it's impossible for `super` to work at all!
+
+Yeah, indeed, let's ask ourselves, how it should technically work? When an object method runs, it gets the current object as `this`. If we call `super.method()` then, the engine needs to get the `method` from the prototype of the current object. But how?
+
+The task may seem simple, but it isn't. The engine knows the current object `this`, so it could get the parent `method` as `this.__proto__.method`. Unfortunately, such a "naive" solution won't work.
+
+Let's demonstrate the problem. Without classes, using plain objects for the sake of simplicity.
+
+You may skip this part and go below to the `[[HomeObject]]` subsection if you don't want to know the details. That won't harm. Or read on if you're interested in understanding things in-depth.
+
+In the example below, `rabbit.__proto__ = animal`. Now let's try: in `rabbit.eat()` we'll call `animal.eat()`, using `this.__proto__`:
+
+```js run
+let animal = {
+ name: "Animal",
+ eat() {
+ alert(`${this.name} eats.`);
+ }
+};
+
+let rabbit = {
+ __proto__: animal,
+ name: "Rabbit",
+ eat() {
+*!*
+ // that's how super.eat() could presumably work
+ this.__proto__.eat.call(this); // (*)
+*/!*
+ }
+};
+
+rabbit.eat(); // Rabbit eats.
+```
+
+At the line `(*)` we take `eat` from the prototype (`animal`) and call it in the context of the current object. Please note that `.call(this)` is important here, because a simple `this.__proto__.eat()` would execute parent `eat` in the context of the prototype, not the current object.
+
+And in the code above it actually works as intended: we have the correct `alert`.
+
+Now let's add one more object to the chain. We'll see how things break:
+
+```js run
+let animal = {
+ name: "Animal",
+ eat() {
+ alert(`${this.name} eats.`);
+ }
+};
+
+let rabbit = {
+ __proto__: animal,
+ eat() {
+ // ...bounce around rabbit-style and call parent (animal) method
+ this.__proto__.eat.call(this); // (*)
+ }
+};
+
+let longEar = {
+ __proto__: rabbit,
+ eat() {
+ // ...do something with long ears and call parent (rabbit) method
+ this.__proto__.eat.call(this); // (**)
+ }
+};
+
+*!*
+longEar.eat(); // Error: Maximum call stack size exceeded
+*/!*
+```
+
+The code doesn't work anymore! We can see the error trying to call `longEar.eat()`.
+
+It may be not that obvious, but if we trace `longEar.eat()` call, then we can see why. In both lines `(*)` and `(**)` the value of `this` is the current object (`longEar`). That's essential: all object methods get the current object as `this`, not a prototype or something.
+
+So, in both lines `(*)` and `(**)` the value of `this.__proto__` is exactly the same: `rabbit`. They both call `rabbit.eat` without going up the chain in the endless loop.
+
+Here's the picture of what happens:
+
+
+
+1. Inside `longEar.eat()`, the line `(**)` calls `rabbit.eat` providing it with `this=longEar`.
+ ```js
+ // inside longEar.eat() we have this = longEar
+ this.__proto__.eat.call(this) // (**)
+ // becomes
+ longEar.__proto__.eat.call(this)
+ // that is
+ rabbit.eat.call(this);
+ ```
+2. Then in the line `(*)` of `rabbit.eat`, we'd like to pass the call even higher in the chain, but `this=longEar`, so `this.__proto__.eat` is again `rabbit.eat`!
+
+ ```js
+ // inside rabbit.eat() we also have this = longEar
+ this.__proto__.eat.call(this) // (*)
+ // becomes
+ longEar.__proto__.eat.call(this)
+ // or (again)
+ rabbit.eat.call(this);
+ ```
+
+3. ...So `rabbit.eat` calls itself in the endless loop, because it can't ascend any further.
+
+The problem can't be solved by using `this` alone.
+
+### `[[HomeObject]]`
+
+To provide the solution, JavaScript adds one more special internal property for functions: `[[HomeObject]]`.
+
+When a function is specified as a class or object method, its `[[HomeObject]]` property becomes that object.
+
+Then `super` uses it to resolve the parent prototype and its methods.
+
+Let's see how it works, first with plain objects:
+
+```js run
+let animal = {
+ name: "Animal",
+ eat() { // animal.eat.[[HomeObject]] == animal
+ alert(`${this.name} eats.`);
+ }
+};
+
+let rabbit = {
+ __proto__: animal,
+ name: "Rabbit",
+ eat() { // rabbit.eat.[[HomeObject]] == rabbit
+ super.eat();
+ }
+};
+
+let longEar = {
+ __proto__: rabbit,
+ name: "Long Ear",
+ eat() { // longEar.eat.[[HomeObject]] == longEar
+ super.eat();
+ }
+};
+
+*!*
+// works correctly
+longEar.eat(); // Long Ear eats.
+*/!*
+```
+
+It works as intended, due to `[[HomeObject]]` mechanics. A method, such as `longEar.eat`, knows its `[[HomeObject]]` and takes the parent method from its prototype. Without any use of `this`.
+
+### Methods are not "free"
+
+As we've known before, generally functions are "free", not bound to objects in JavaScript. So they can be copied between objects and called with another `this`.
+
+The very existence of `[[HomeObject]]` violates that principle, because methods remember their objects. `[[HomeObject]]` can't be changed, so this bond is forever.
+
+The only place in the language where `[[HomeObject]]` is used -- is `super`. So, if a method does not use `super`, then we can still consider it free and copy between objects. But with `super` things may go wrong.
+
+Here's the demo of a wrong `super` result after copying:
+
+```js run
+let animal = {
+ sayHi() {
+ alert(`I'm an animal`);
+ }
+};
+
+// rabbit inherits from animal
+let rabbit = {
+ __proto__: animal,
+ sayHi() {
+ super.sayHi();
+ }
+};
+
+let plant = {
+ sayHi() {
+ alert("I'm a plant");
+ }
+};
+
+// tree inherits from plant
+let tree = {
+ __proto__: plant,
+*!*
+ sayHi: rabbit.sayHi // (*)
+*/!*
+};
+
+*!*
+tree.sayHi(); // I'm an animal (?!?)
+*/!*
+```
+
+A call to `tree.sayHi()` shows "I'm an animal". Definitely wrong.
+
+The reason is simple:
+- In the line `(*)`, the method `tree.sayHi` was copied from `rabbit`. Maybe we just wanted to avoid code duplication?
+- Its `[[HomeObject]]` is `rabbit`, as it was created in `rabbit`. There's no way to change `[[HomeObject]]`.
+- The code of `tree.sayHi()` has `super.sayHi()` inside. It goes up from `rabbit` and takes the method from `animal`.
+
+Here's the diagram of what happens:
+
+
+
+### Methods, not function properties
+
+`[[HomeObject]]` is defined for methods both in classes and in plain objects. But for objects, methods must be specified exactly as `method()`, not as `"method: function()"`.
+
+The difference may be non-essential for us, but it's important for JavaScript.
+
+In the example below a non-method syntax is used for comparison. `[[HomeObject]]` property is not set and the inheritance doesn't work:
+
+```js run
+let animal = {
+ eat: function() { // intentionally writing like this instead of eat() {...
+ // ...
+ }
+};
+
+let rabbit = {
+ __proto__: animal,
+ eat: function() {
+ super.eat();
+ }
+};
+
+*!*
+rabbit.eat(); // Error calling super (because there's no [[HomeObject]])
+*/!*
+```
+
+## Summary
+
+1. To extend a class: `class Child extends Parent`:
+ - That means `Child.prototype.__proto__` will be `Parent.prototype`, so methods are inherited.
+2. When overriding a constructor:
+ - We must call parent constructor as `super()` in `Child` constructor before using `this`.
+3. When overriding another method:
+ - We can use `super.method()` in a `Child` method to call `Parent` method.
+4. Internals:
+ - Methods remember their class/object in the internal `[[HomeObject]]` property. That's how `super` resolves parent methods.
+ - So it's not safe to copy a method with `super` from one object to another.
+
+Also:
+- Arrow functions don't have their own `this` or `super`, so they transparently fit into the surrounding context.
diff --git a/1-js/09-classes/02-class-inheritance/class-inheritance-array-object.svg b/1-js/09-classes/02-class-inheritance/class-inheritance-array-object.svg
new file mode 100644
index 0000000000..5ea9bf29ea
--- /dev/null
+++ b/1-js/09-classes/02-class-inheritance/class-inheritance-array-object.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/09-classes/02-class-inheritance/class-inheritance-rabbit-animal-2.svg b/1-js/09-classes/02-class-inheritance/class-inheritance-rabbit-animal-2.svg
new file mode 100644
index 0000000000..72e47e34c2
--- /dev/null
+++ b/1-js/09-classes/02-class-inheritance/class-inheritance-rabbit-animal-2.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/09-classes/02-class-inheritance/class-inheritance-rabbit-animal.svg b/1-js/09-classes/02-class-inheritance/class-inheritance-rabbit-animal.svg
new file mode 100644
index 0000000000..bced3d355e
--- /dev/null
+++ b/1-js/09-classes/02-class-inheritance/class-inheritance-rabbit-animal.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/09-classes/02-class-inheritance/rabbit-animal-independent-animal.svg b/1-js/09-classes/02-class-inheritance/rabbit-animal-independent-animal.svg
new file mode 100644
index 0000000000..f53fc92dee
--- /dev/null
+++ b/1-js/09-classes/02-class-inheritance/rabbit-animal-independent-animal.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/09-classes/02-class-inheritance/rabbit-animal-independent-rabbit.svg b/1-js/09-classes/02-class-inheritance/rabbit-animal-independent-rabbit.svg
new file mode 100644
index 0000000000..2f30a3a901
--- /dev/null
+++ b/1-js/09-classes/02-class-inheritance/rabbit-animal-independent-rabbit.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/09-classes/02-class-inheritance/super-homeobject-wrong.svg b/1-js/09-classes/02-class-inheritance/super-homeobject-wrong.svg
new file mode 100644
index 0000000000..f6450ddc49
--- /dev/null
+++ b/1-js/09-classes/02-class-inheritance/super-homeobject-wrong.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/09-classes/02-class-inheritance/this-super-loop.svg b/1-js/09-classes/02-class-inheritance/this-super-loop.svg
new file mode 100644
index 0000000000..4f5f45034a
--- /dev/null
+++ b/1-js/09-classes/02-class-inheritance/this-super-loop.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/09-classes/03-static-properties-methods/3-class-extend-object/rabbit-extends-object.svg b/1-js/09-classes/03-static-properties-methods/3-class-extend-object/rabbit-extends-object.svg
new file mode 100644
index 0000000000..915ab9aa64
--- /dev/null
+++ b/1-js/09-classes/03-static-properties-methods/3-class-extend-object/rabbit-extends-object.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/09-classes/03-static-properties-methods/3-class-extend-object/solution.md b/1-js/09-classes/03-static-properties-methods/3-class-extend-object/solution.md
new file mode 100644
index 0000000000..cb9829ce05
--- /dev/null
+++ b/1-js/09-classes/03-static-properties-methods/3-class-extend-object/solution.md
@@ -0,0 +1,81 @@
+First, let's see why the latter code doesn't work.
+
+The reason becomes obvious if we try to run it. An inheriting class constructor must call `super()`. Otherwise `"this"` won't be "defined".
+
+So here's the fix:
+
+```js run
+class Rabbit extends Object {
+ constructor(name) {
+*!*
+ super(); // need to call the parent constructor when inheriting
+*/!*
+ this.name = name;
+ }
+}
+
+let rabbit = new Rabbit("Rab");
+
+alert( rabbit.hasOwnProperty('name') ); // true
+```
+
+But that's not all yet.
+
+Even after the fix, there's still an important difference between `"class Rabbit extends Object"` and `class Rabbit`.
+
+As we know, the "extends" syntax sets up two prototypes:
+
+1. Between `"prototype"` of the constructor functions (for methods).
+2. Between the constructor functions themselves (for static methods).
+
+In the case of `class Rabbit extends Object` it means:
+
+```js run
+class Rabbit extends Object {}
+
+alert( Rabbit.prototype.__proto__ === Object.prototype ); // (1) true
+alert( Rabbit.__proto__ === Object ); // (2) true
+```
+
+So `Rabbit` now provides access to the static methods of `Object` via `Rabbit`, like this:
+
+```js run
+class Rabbit extends Object {}
+
+*!*
+// normally we call Object.getOwnPropertyNames
+alert ( Rabbit.getOwnPropertyNames({a: 1, b: 2})); // a,b
+*/!*
+```
+
+But if we don't have `extends Object`, then `Rabbit.__proto__` is not set to `Object`.
+
+Here's the demo:
+
+```js run
+class Rabbit {}
+
+alert( Rabbit.prototype.__proto__ === Object.prototype ); // (1) true
+alert( Rabbit.__proto__ === Object ); // (2) false (!)
+alert( Rabbit.__proto__ === Function.prototype ); // as any function by default
+
+*!*
+// error, no such function in Rabbit
+alert ( Rabbit.getOwnPropertyNames({a: 1, b: 2})); // Error
+*/!*
+```
+
+So `Rabbit` doesn't provide access to static methods of `Object` in that case.
+
+By the way, `Function.prototype` also has "generic" function methods, like `call`, `bind` etc. They are ultimately available in both cases, because for the built-in `Object` constructor, `Object.__proto__ === Function.prototype`.
+
+Here's the picture:
+
+
+
+So, to put it short, there are two differences:
+
+| class Rabbit | class Rabbit extends Object |
+|--------------|------------------------------|
+| -- | needs to call `super()` in constructor |
+| `Rabbit.__proto__ === Function.prototype` | `Rabbit.__proto__ === Object` |
diff --git a/1-js/09-classes/03-static-properties-methods/3-class-extend-object/task.md b/1-js/09-classes/03-static-properties-methods/3-class-extend-object/task.md
new file mode 100644
index 0000000000..1d0f98a74e
--- /dev/null
+++ b/1-js/09-classes/03-static-properties-methods/3-class-extend-object/task.md
@@ -0,0 +1,42 @@
+importance: 3
+
+---
+
+# Class extends Object?
+
+As we know, all objects normally inherit from `Object.prototype` and get access to "generic" object methods like `hasOwnProperty` etc.
+
+For instance:
+
+```js run
+class Rabbit {
+ constructor(name) {
+ this.name = name;
+ }
+}
+
+let rabbit = new Rabbit("Rab");
+
+*!*
+// hasOwnProperty method is from Object.prototype
+alert( rabbit.hasOwnProperty('name') ); // true
+*/!*
+```
+
+But if we spell it out explicitly like `"class Rabbit extends Object"`, then the result would be different from a simple `"class Rabbit"`?
+
+What's the difference?
+
+Here's an example of such code (it doesn't work -- why? fix it?):
+
+```js
+class Rabbit extends Object {
+ constructor(name) {
+ this.name = name;
+ }
+}
+
+let rabbit = new Rabbit("Rab");
+
+alert( rabbit.hasOwnProperty('name') ); // Error
+```
diff --git a/1-js/09-classes/03-static-properties-methods/animal-rabbit-static.svg b/1-js/09-classes/03-static-properties-methods/animal-rabbit-static.svg
new file mode 100644
index 0000000000..3e354b895d
--- /dev/null
+++ b/1-js/09-classes/03-static-properties-methods/animal-rabbit-static.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/09-classes/03-static-properties-methods/article.md b/1-js/09-classes/03-static-properties-methods/article.md
new file mode 100644
index 0000000000..4b493a5e8b
--- /dev/null
+++ b/1-js/09-classes/03-static-properties-methods/article.md
@@ -0,0 +1,249 @@
+
+# Static properties and methods
+
+We can also assign a method to the class as a whole. Such methods are called *static*.
+
+In a class declaration, they are prepended by `static` keyword, like this:
+
+```js run
+class User {
+*!*
+ static staticMethod() {
+*/!*
+ alert(this === User);
+ }
+}
+
+User.staticMethod(); // true
+```
+
+That actually does the same as assigning it as a property directly:
+
+```js run
+class User { }
+
+User.staticMethod = function() {
+ alert(this === User);
+};
+
+User.staticMethod(); // true
+```
+
+The value of `this` in `User.staticMethod()` call is the class constructor `User` itself (the "object before dot" rule).
+
+Usually, static methods are used to implement functions that belong to the class as a whole, but not to any particular object of it.
+
+For instance, we have `Article` objects and need a function to compare them.
+
+A natural solution would be to add `Article.compare` static method:
+
+```js run
+class Article {
+ constructor(title, date) {
+ this.title = title;
+ this.date = date;
+ }
+
+*!*
+ static compare(articleA, articleB) {
+ return articleA.date - articleB.date;
+ }
+*/!*
+}
+
+// usage
+let articles = [
+ new Article("HTML", new Date(2019, 1, 1)),
+ new Article("CSS", new Date(2019, 0, 1)),
+ new Article("JavaScript", new Date(2019, 11, 1))
+];
+
+*!*
+articles.sort(Article.compare);
+*/!*
+
+alert( articles[0].title ); // CSS
+```
+
+Here `Article.compare` method stands "above" articles, as a means to compare them. It's not a method of an article, but rather of the whole class.
+
+Another example would be a so-called "factory" method.
+
+Let's say, we need multiple ways to create an article:
+
+1. Create by given parameters (`title`, `date` etc).
+2. Create an empty article with today's date.
+3. ...or else somehow.
+
+The first way can be implemented by the constructor. And for the second one we can make a static method of the class.
+
+Such as `Article.createTodays()` here:
+
+```js run
+class Article {
+ constructor(title, date) {
+ this.title = title;
+ this.date = date;
+ }
+
+*!*
+ static createTodays() {
+ // remember, this = Article
+ return new this("Today's digest", new Date());
+ }
+*/!*
+}
+
+let article = Article.createTodays();
+
+alert( article.title ); // Today's digest
+```
+
+Now every time we need to create a today's digest, we can call `Article.createTodays()`. Once again, that's not a method of an article, but a method of the whole class.
+
+Static methods are also used in database-related classes to search/save/remove entries from the database, like this:
+
+```js
+// assuming Article is a special class for managing articles
+// static method to remove the article by id:
+Article.remove({id: 12345});
+```
+
+````warn header="Static methods aren't available for individual objects"
+Static methods are callable on classes, not on individual objects.
+
+E.g. such code won't work:
+
+```js
+// ...
+article.createTodays(); /// Error: article.createTodays is not a function
+```
+````
+
+## Static properties
+
+[recent browser=Chrome]
+
+Static properties are also possible, they look like regular class properties, but prepended by `static`:
+
+```js run
+class Article {
+ static publisher = "Ilya Kantor";
+}
+
+alert( Article.publisher ); // Ilya Kantor
+```
+
+That is the same as a direct assignment to `Article`:
+
+```js
+Article.publisher = "Ilya Kantor";
+```
+
+## Inheritance of static properties and methods [#statics-and-inheritance]
+
+Static properties and methods are inherited.
+
+For instance, `Animal.compare` and `Animal.planet` in the code below are inherited and accessible as `Rabbit.compare` and `Rabbit.planet`:
+
+```js run
+class Animal {
+ static planet = "Earth";
+
+ constructor(name, speed) {
+ this.speed = speed;
+ this.name = name;
+ }
+
+ run(speed = 0) {
+ this.speed += speed;
+ alert(`${this.name} runs with speed ${this.speed}.`);
+ }
+
+*!*
+ static compare(animalA, animalB) {
+ return animalA.speed - animalB.speed;
+ }
+*/!*
+
+}
+
+// Inherit from Animal
+class Rabbit extends Animal {
+ hide() {
+ alert(`${this.name} hides!`);
+ }
+}
+
+let rabbits = [
+ new Rabbit("White Rabbit", 10),
+ new Rabbit("Black Rabbit", 5)
+];
+
+*!*
+rabbits.sort(Rabbit.compare);
+*/!*
+
+rabbits[0].run(); // Black Rabbit runs with speed 5.
+
+alert(Rabbit.planet); // Earth
+```
+
+Now when we call `Rabbit.compare`, the inherited `Animal.compare` will be called.
+
+How does it work? Again, using prototypes. As you might have already guessed, `extends` gives `Rabbit` the `[[Prototype]]` reference to `Animal`.
+
+
+
+So, `Rabbit extends Animal` creates two `[[Prototype]]` references:
+
+1. `Rabbit` function prototypally inherits from `Animal` function.
+2. `Rabbit.prototype` prototypally inherits from `Animal.prototype`.
+
+As a result, inheritance works both for regular and static methods.
+
+Here, let's check that by code:
+
+```js run
+class Animal {}
+class Rabbit extends Animal {}
+
+// for statics
+alert(Rabbit.__proto__ === Animal); // true
+
+// for regular methods
+alert(Rabbit.prototype.__proto__ === Animal.prototype); // true
+```
+
+## Summary
+
+Static methods are used for the functionality that belongs to the class "as a whole". It doesn't relate to a concrete class instance.
+
+For example, a method for comparison `Article.compare(article1, article2)` or a factory method `Article.createTodays()`.
+
+They are labeled by the word `static` in class declaration.
+
+Static properties are used when we'd like to store class-level data, also not bound to an instance.
+
+The syntax is:
+
+```js
+class MyClass {
+ static property = ...;
+
+ static method() {
+ ...
+ }
+}
+```
+
+Technically, static declaration is the same as assigning to the class itself:
+
+```js
+MyClass.property = ...
+MyClass.method = ...
+```
+
+Static properties and methods are inherited.
+
+For `class B extends A` the prototype of the class `B` itself points to `A`: `B.[[Prototype]] = A`. So if a field is not found in `B`, the search continues in `A`.
diff --git a/1-js/09-classes/04-private-protected-properties-methods/article.md b/1-js/09-classes/04-private-protected-properties-methods/article.md
new file mode 100644
index 0000000000..91efb89eeb
--- /dev/null
+++ b/1-js/09-classes/04-private-protected-properties-methods/article.md
@@ -0,0 +1,322 @@
+
+# Private and protected properties and methods
+
+One of the most important principles of object oriented programming -- delimiting internal interface from the external one.
+
+That is "a must" practice in developing anything more complex than a "hello world" app.
+
+To understand this, let's break away from development and turn our eyes into the real world.
+
+Usually, devices that we're using are quite complex. But delimiting the internal interface from the external one allows to use them without problems.
+
+## A real-life example
+
+For instance, a coffee machine. Simple from outside: a button, a display, a few holes...And, surely, the result -- great coffee! :)
+
+
+
+But inside... (a picture from the repair manual)
+
+
+
+A lot of details. But we can use it without knowing anything.
+
+Coffee machines are quite reliable, aren't they? We can use one for years, and only if something goes wrong -- bring it for repairs.
+
+The secret of reliability and simplicity of a coffee machine -- all details are well-tuned and *hidden* inside.
+
+If we remove the protective cover from the coffee machine, then using it will be much more complex (where to press?), and dangerous (it can electrocute).
+
+As we'll see, in programming objects are like coffee machines.
+
+But in order to hide inner details, we'll use not a protective cover, but rather special syntax of the language and conventions.
+
+## Internal and external interface
+
+In object-oriented programming, properties and methods are split into two groups:
+
+- *Internal interface* -- methods and properties, accessible from other methods of the class, but not from the outside.
+- *External interface* -- methods and properties, accessible also from outside the class.
+
+If we continue the analogy with the coffee machine -- what's hidden inside: a boiler tube, heating element, and so on -- is its internal interface.
+
+An internal interface is used for the object to work, its details use each other. For instance, a boiler tube is attached to the heating element.
+
+But from the outside a coffee machine is closed by the protective cover, so that no one can reach those. Details are hidden and inaccessible. We can use its features via the external interface.
+
+So, all we need to use an object is to know its external interface. We may be completely unaware how it works inside, and that's great.
+
+That was a general introduction.
+
+In JavaScript, there are two types of object fields (properties and methods):
+
+- Public: accessible from anywhere. They comprise the external interface. Until now we were only using public properties and methods.
+- Private: accessible only from inside the class. These are for the internal interface.
+
+In many other languages there also exist "protected" fields: accessible only from inside the class and those extending it (like private, but plus access from inheriting classes). They are also useful for the internal interface. They are in a sense more widespread than private ones, because we usually want inheriting classes to gain access to them.
+
+Protected fields are not implemented in JavaScript on the language level, but in practice they are very convenient, so they are emulated.
+
+Now we'll make a coffee machine in JavaScript with all these types of properties. A coffee machine has a lot of details, we won't model them to stay simple (though we could).
+
+## Protecting "waterAmount"
+
+Let's make a simple coffee machine class first:
+
+```js run
+class CoffeeMachine {
+ waterAmount = 0; // the amount of water inside
+
+ constructor(power) {
+ this.power = power;
+ alert( `Created a coffee-machine, power: ${power}` );
+ }
+
+}
+
+// create the coffee machine
+let coffeeMachine = new CoffeeMachine(100);
+
+// add water
+coffeeMachine.waterAmount = 200;
+```
+
+Right now the properties `waterAmount` and `power` are public. We can easily get/set them from the outside to any value.
+
+Let's change `waterAmount` property to protected to have more control over it. For instance, we don't want anyone to set it below zero.
+
+**Protected properties are usually prefixed with an underscore `_`.**
+
+That is not enforced on the language level, but there's a well-known convention between programmers that such properties and methods should not be accessed from the outside.
+
+So our property will be called `_waterAmount`:
+
+```js run
+class CoffeeMachine {
+ _waterAmount = 0;
+
+ set waterAmount(value) {
+ if (value < 0) {
+ value = 0;
+ }
+ this._waterAmount = value;
+ }
+
+ get waterAmount() {
+ return this._waterAmount;
+ }
+
+ constructor(power) {
+ this._power = power;
+ }
+
+}
+
+// create the coffee machine
+let coffeeMachine = new CoffeeMachine(100);
+
+// add water
+coffeeMachine.waterAmount = -10; // _waterAmount will become 0, not -10
+```
+
+Now the access is under control, so setting the water amount below zero becomes impossible.
+
+## Read-only "power"
+
+For `power` property, let's make it read-only. It sometimes happens that a property must be set at creation time only, and then never modified.
+
+That's exactly the case for a coffee machine: power never changes.
+
+To do so, we only need to make getter, but not the setter:
+
+```js run
+class CoffeeMachine {
+ // ...
+
+ constructor(power) {
+ this._power = power;
+ }
+
+ get power() {
+ return this._power;
+ }
+
+}
+
+// create the coffee machine
+let coffeeMachine = new CoffeeMachine(100);
+
+alert(`Power is: ${coffeeMachine.power}W`); // Power is: 100W
+
+coffeeMachine.power = 25; // Error (no setter)
+```
+
+````smart header="Getter/setter functions"
+Here we used getter/setter syntax.
+
+But most of the time `get.../set...` functions are preferred, like this:
+
+```js
+class CoffeeMachine {
+ _waterAmount = 0;
+
+ *!*setWaterAmount(value)*/!* {
+ if (value < 0) value = 0;
+ this._waterAmount = value;
+ }
+
+ *!*getWaterAmount()*/!* {
+ return this._waterAmount;
+ }
+}
+
+new CoffeeMachine().setWaterAmount(100);
+```
+
+That looks a bit longer, but functions are more flexible. They can accept multiple arguments (even if we don't need them right now).
+
+On the other hand, get/set syntax is shorter, so ultimately there's no strict rule, it's up to you to decide.
+````
+
+```smart header="Protected fields are inherited"
+If we inherit `class MegaMachine extends CoffeeMachine`, then nothing prevents us from accessing `this._waterAmount` or `this._power` from the methods of the new class.
+
+So protected fields are naturally inheritable. Unlike private ones that we'll see below.
+```
+
+## Private "#waterLimit"
+
+[recent browser=none]
+
+There's a finished JavaScript proposal, almost in the standard, that provides language-level support for private properties and methods.
+
+Privates should start with `#`. They are only accessible from inside the class.
+
+For instance, here's a private `#waterLimit` property and the water-checking private method `#fixWaterAmount`:
+
+```js run
+class CoffeeMachine {
+*!*
+ #waterLimit = 200;
+*/!*
+
+*!*
+ #fixWaterAmount(value) {
+ if (value < 0) return 0;
+ if (value > this.#waterLimit) return this.#waterLimit;
+ }
+*/!*
+
+ setWaterAmount(value) {
+ this.#waterLimit = this.#fixWaterAmount(value);
+ }
+
+}
+
+let coffeeMachine = new CoffeeMachine();
+
+*!*
+// can't access privates from outside of the class
+coffeeMachine.#fixWaterAmount(123); // Error
+coffeeMachine.#waterLimit = 1000; // Error
+*/!*
+```
+
+On the language level, `#` is a special sign that the field is private. We can't access it from outside or from inheriting classes.
+
+Private fields do not conflict with public ones. We can have both private `#waterAmount` and public `waterAmount` fields at the same time.
+
+For instance, let's make `waterAmount` an accessor for `#waterAmount`:
+
+```js run
+class CoffeeMachine {
+
+ #waterAmount = 0;
+
+ get waterAmount() {
+ return this.#waterAmount;
+ }
+
+ set waterAmount(value) {
+ if (value < 0) value = 0;
+ this.#waterAmount = value;
+ }
+}
+
+let machine = new CoffeeMachine();
+
+machine.waterAmount = 100;
+alert(machine.#waterAmount); // Error
+```
+
+Unlike protected ones, private fields are enforced by the language itself. That's a good thing.
+
+But if we inherit from `CoffeeMachine`, then we'll have no direct access to `#waterAmount`. We'll need to rely on `waterAmount` getter/setter:
+
+```js
+class MegaCoffeeMachine extends CoffeeMachine {
+ method() {
+*!*
+ alert( this.#waterAmount ); // Error: can only access from CoffeeMachine
+*/!*
+ }
+}
+```
+
+In many scenarios such limitation is too severe. If we extend a `CoffeeMachine`, we may have legitimate reasons to access its internals. That's why protected fields are used more often, even though they are not supported by the language syntax.
+
+````warn header="Private fields are not available as this[name]"
+Private fields are special.
+
+As we know, usually we can access fields using `this[name]`:
+
+```js
+class User {
+ ...
+ sayHi() {
+ let fieldName = "name";
+ alert(`Hello, ${*!*this[fieldName]*/!*}`);
+ }
+}
+```
+
+With private fields that's impossible: `this['#name']` doesn't work. That's a syntax limitation to ensure privacy.
+````
+
+## Summary
+
+In terms of OOP, delimiting of the internal interface from the external one is called [encapsulation](https://en.wikipedia.org/wiki/Encapsulation_(computer_programming)).
+
+It gives the following benefits:
+
+Protection for users, so that they don't shoot themselves in the foot
+: Imagine, there's a team of developers using a coffee machine. It was made by the "Best CoffeeMachine" company, and works fine, but a protective cover was removed. So the internal interface is exposed.
+
+ All developers are civilized -- they use the coffee machine as intended. But one of them, John, decided that he's the smartest one, and made some tweaks in the coffee machine internals. So the coffee machine failed two days later.
+
+ That's surely not John's fault, but rather the person who removed the protective cover and let John do his manipulations.
+
+ The same in programming. If a user of a class will change things not intended to be changed from the outside -- the consequences are unpredictable.
+
+Supportable
+: The situation in programming is more complex than with a real-life coffee machine, because we don't just buy it once. The code constantly undergoes development and improvement.
+
+ **If we strictly delimit the internal interface, then the developer of the class can freely change its internal properties and methods, even without informing the users.**
+
+ If you're a developer of such class, it's great to know that private methods can be safely renamed, their parameters can be changed, and even removed, because no external code depends on them.
+
+ For users, when a new version comes out, it may be a total overhaul internally, but still simple to upgrade if the external interface is the same.
+
+Hiding complexity
+: People adore using things that are simple. At least from outside. What's inside is a different thing.
+
+ Programmers are not an exception.
+
+ **It's always convenient when implementation details are hidden, and a simple, well-documented external interface is available.**
+
+To hide an internal interface we use either protected or private properties:
+
+- Protected fields start with `_`. That's a well-known convention, not enforced at the language level. Programmers should only access a field starting with `_` from its class and classes inheriting from it.
+- Private fields start with `#`. JavaScript makes sure we can only access those from inside the class.
+
+Right now, private fields are not well-supported among browsers, but can be polyfilled.
diff --git a/1-js/09-classes/04-private-protected-properties-methods/coffee-inside.jpg b/1-js/09-classes/04-private-protected-properties-methods/coffee-inside.jpg
new file mode 100644
index 0000000000..60f84664d1
Binary files /dev/null and b/1-js/09-classes/04-private-protected-properties-methods/coffee-inside.jpg differ
diff --git a/1-js/09-classes/04-private-protected-properties-methods/coffee.jpg b/1-js/09-classes/04-private-protected-properties-methods/coffee.jpg
new file mode 100644
index 0000000000..ee26e1c064
Binary files /dev/null and b/1-js/09-classes/04-private-protected-properties-methods/coffee.jpg differ
diff --git a/1-js/09-classes/05-extend-natives/article.md b/1-js/09-classes/05-extend-natives/article.md
new file mode 100644
index 0000000000..28b4c6eb64
--- /dev/null
+++ b/1-js/09-classes/05-extend-natives/article.md
@@ -0,0 +1,89 @@
+
+# Extending built-in classes
+
+Built-in classes like Array, Map and others are extendable also.
+
+For instance, here `PowerArray` inherits from the native `Array`:
+
+```js run
+// add one more method to it (can do more)
+class PowerArray extends Array {
+ isEmpty() {
+ return this.length === 0;
+ }
+}
+
+let arr = new PowerArray(1, 2, 5, 10, 50);
+alert(arr.isEmpty()); // false
+
+let filteredArr = arr.filter(item => item >= 10);
+alert(filteredArr); // 10, 50
+alert(filteredArr.isEmpty()); // false
+```
+
+Please note a very interesting thing. Built-in methods like `filter`, `map` and others -- return new objects of exactly the inherited type `PowerArray`. Their internal implementation uses the object's `constructor` property for that.
+
+In the example above,
+```js
+arr.constructor === PowerArray
+```
+
+When `arr.filter()` is called, it internally creates the new array of results using exactly `arr.constructor`, not basic `Array`. That's actually very cool, because we can keep using `PowerArray` methods further on the result.
+
+Even more, we can customize that behavior.
+
+We can add a special static getter `Symbol.species` to the class. If it exists, it should return the constructor that JavaScript will use internally to create new entities in `map`, `filter` and so on.
+
+If we'd like built-in methods like `map` or `filter` to return regular arrays, we can return `Array` in `Symbol.species`, like here:
+
+```js run
+class PowerArray extends Array {
+ isEmpty() {
+ return this.length === 0;
+ }
+
+*!*
+ // built-in methods will use this as the constructor
+ static get [Symbol.species]() {
+ return Array;
+ }
+*/!*
+}
+
+let arr = new PowerArray(1, 2, 5, 10, 50);
+alert(arr.isEmpty()); // false
+
+// filter creates new array using arr.constructor[Symbol.species] as constructor
+let filteredArr = arr.filter(item => item >= 10);
+
+*!*
+// filteredArr is not PowerArray, but Array
+*/!*
+alert(filteredArr.isEmpty()); // Error: filteredArr.isEmpty is not a function
+```
+
+As you can see, now `.filter` returns `Array`. So the extended functionality is not passed any further.
+
+```smart header="Other collections work similarly"
+Other collections, such as `Map` and `Set`, work alike. They also use `Symbol.species`.
+```
+
+## No static inheritance in built-ins
+
+Built-in objects have their own static methods, for instance `Object.keys`, `Array.isArray` etc.
+
+As we already know, native classes extend each other. For instance, `Array` extends `Object`.
+
+Normally, when one class extends another, both static and non-static methods are inherited. That was thoroughly explained in the article [](info:static-properties-methods#statics-and-inheritance).
+
+But built-in classes are an exception. They don't inherit statics from each other.
+
+For example, both `Array` and `Date` inherit from `Object`, so their instances have methods from `Object.prototype`. But `Array.[[Prototype]]` does not reference `Object`, so there's no, for instance, `Array.keys()` (or `Date.keys()`) static method.
+
+Here's the picture structure for `Date` and `Object`:
+
+
+
+As you can see, there's no link between `Date` and `Object`. They are independent, only `Date.prototype` inherits from `Object.prototype`.
+
+That's an important difference of inheritance between built-in objects compared to what we get with `extends`.
diff --git a/1-js/09-classes/05-extend-natives/object-date-inheritance.svg b/1-js/09-classes/05-extend-natives/object-date-inheritance.svg
new file mode 100644
index 0000000000..be47d7fd96
--- /dev/null
+++ b/1-js/09-classes/05-extend-natives/object-date-inheritance.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/07-object-oriented-programming/11-instanceof/1-strange-instanceof/solution.md b/1-js/09-classes/06-instanceof/1-strange-instanceof/solution.md
similarity index 100%
rename from 1-js/07-object-oriented-programming/11-instanceof/1-strange-instanceof/solution.md
rename to 1-js/09-classes/06-instanceof/1-strange-instanceof/solution.md
diff --git a/1-js/09-classes/06-instanceof/1-strange-instanceof/task.md b/1-js/09-classes/06-instanceof/1-strange-instanceof/task.md
new file mode 100644
index 0000000000..5b8dc7de3c
--- /dev/null
+++ b/1-js/09-classes/06-instanceof/1-strange-instanceof/task.md
@@ -0,0 +1,20 @@
+importance: 5
+
+---
+
+# Strange instanceof
+
+In the code below, why does `instanceof` return `true`? We can easily see that `a` is not created by `B()`.
+
+```js run
+function A() {}
+function B() {}
+
+A.prototype = B.prototype = {};
+
+let a = new A();
+
+*!*
+alert( a instanceof B ); // true
+*/!*
+```
diff --git a/1-js/09-classes/06-instanceof/article.md b/1-js/09-classes/06-instanceof/article.md
new file mode 100644
index 0000000000..f9db989ca9
--- /dev/null
+++ b/1-js/09-classes/06-instanceof/article.md
@@ -0,0 +1,218 @@
+# Class checking: "instanceof"
+
+The `instanceof` operator allows to check whether an object belongs to a certain class. It also takes inheritance into account.
+
+Such a check may be necessary in many cases. For example, it can be used for building a *polymorphic* function, the one that treats arguments differently depending on their type.
+
+## The instanceof operator [#ref-instanceof]
+
+The syntax is:
+```js
+obj instanceof Class
+```
+
+It returns `true` if `obj` belongs to the `Class` or a class inheriting from it.
+
+For instance:
+
+```js run
+class Rabbit {}
+let rabbit = new Rabbit();
+
+// is it an object of Rabbit class?
+*!*
+alert( rabbit instanceof Rabbit ); // true
+*/!*
+```
+
+It also works with constructor functions:
+
+```js run
+*!*
+// instead of class
+function Rabbit() {}
+*/!*
+
+alert( new Rabbit() instanceof Rabbit ); // true
+```
+
+...And with built-in classes like `Array`:
+
+```js run
+let arr = [1, 2, 3];
+alert( arr instanceof Array ); // true
+alert( arr instanceof Object ); // true
+```
+
+Please note that `arr` also belongs to the `Object` class. That's because `Array` prototypically inherits from `Object`.
+
+Normally, `instanceof` examines the prototype chain for the check. We can also set a custom logic in the static method `Symbol.hasInstance`.
+
+The algorithm of `obj instanceof Class` works roughly as follows:
+
+1. If there's a static method `Symbol.hasInstance`, then just call it: `Class[Symbol.hasInstance](obj)`. It should return either `true` or `false`, and we're done. That's how we can customize the behavior of `instanceof`.
+
+ For example:
+
+ ```js run
+ // setup instanceOf check that assumes that
+ // anything with canEat property is an animal
+ class Animal {
+ static [Symbol.hasInstance](obj) {
+ if (obj.canEat) return true;
+ }
+ }
+
+ let obj = { canEat: true };
+
+ alert(obj instanceof Animal); // true: Animal[Symbol.hasInstance](obj) is called
+ ```
+
+2. Most classes do not have `Symbol.hasInstance`. In that case, the standard logic is used: `obj instanceOf Class` checks whether `Class.prototype` is equal to one of the prototypes in the `obj` prototype chain.
+
+ In other words, compare one after another:
+ ```js
+ obj.__proto__ === Class.prototype?
+ obj.__proto__.__proto__ === Class.prototype?
+ obj.__proto__.__proto__.__proto__ === Class.prototype?
+ ...
+ // if any answer is true, return true
+ // otherwise, if we reached the end of the chain, return false
+ ```
+
+ In the example above `rabbit.__proto__ === Rabbit.prototype`, so that gives the answer immediately.
+
+ In the case of an inheritance, the match will be at the second step:
+
+ ```js run
+ class Animal {}
+ class Rabbit extends Animal {}
+
+ let rabbit = new Rabbit();
+ *!*
+ alert(rabbit instanceof Animal); // true
+ */!*
+
+ // rabbit.__proto__ === Animal.prototype (no match)
+ *!*
+ // rabbit.__proto__.__proto__ === Animal.prototype (match!)
+ */!*
+ ```
+
+Here's the illustration of what `rabbit instanceof Animal` compares with `Animal.prototype`:
+
+
+
+By the way, there's also a method [objA.isPrototypeOf(objB)](mdn:js/object/isPrototypeOf), that returns `true` if `objA` is somewhere in the chain of prototypes for `objB`. So the test of `obj instanceof Class` can be rephrased as `Class.prototype.isPrototypeOf(obj)`.
+
+It's funny, but the `Class` constructor itself does not participate in the check! Only the chain of prototypes and `Class.prototype` matters.
+
+That can lead to interesting consequences when a `prototype` property is changed after the object is created.
+
+Like here:
+
+```js run
+function Rabbit() {}
+let rabbit = new Rabbit();
+
+// changed the prototype
+Rabbit.prototype = {};
+
+// ...not a rabbit any more!
+*!*
+alert( rabbit instanceof Rabbit ); // false
+*/!*
+```
+
+## Bonus: Object.prototype.toString for the type
+
+We already know that plain objects are converted to string as `[object Object]`:
+
+```js run
+let obj = {};
+
+alert(obj); // [object Object]
+alert(obj.toString()); // the same
+```
+
+That's their implementation of `toString`. But there's a hidden feature that makes `toString` actually much more powerful than that. We can use it as an extended `typeof` and an alternative for `instanceof`.
+
+Sounds strange? Indeed. Let's demystify.
+
+By [specification](https://tc39.github.io/ecma262/#sec-object.prototype.tostring), the built-in `toString` can be extracted from the object and executed in the context of any other value. And its result depends on that value.
+
+- For a number, it will be `[object Number]`
+- For a boolean, it will be `[object Boolean]`
+- For `null`: `[object Null]`
+- For `undefined`: `[object Undefined]`
+- For arrays: `[object Array]`
+- ...etc (customizable).
+
+Let's demonstrate:
+
+```js run
+// copy toString method into a variable for convenience
+let objectToString = Object.prototype.toString;
+
+// what type is this?
+let arr = [];
+
+alert( objectToString.call(arr) ); // [object *!*Array*/!*]
+```
+
+Here we used [call](mdn:js/function/call) as described in the chapter [](info:call-apply-decorators) to execute the function `objectToString` in the context `this=arr`.
+
+Internally, the `toString` algorithm examines `this` and returns the corresponding result. More examples:
+
+```js run
+let s = Object.prototype.toString;
+
+alert( s.call(123) ); // [object Number]
+alert( s.call(null) ); // [object Null]
+alert( s.call(alert) ); // [object Function]
+```
+
+### Symbol.toStringTag
+
+The behavior of Object `toString` can be customized using a special object property `Symbol.toStringTag`.
+
+For instance:
+
+```js run
+let user = {
+ [Symbol.toStringTag]: "User"
+};
+
+alert( {}.toString.call(user) ); // [object User]
+```
+
+For most environment-specific objects, there is such a property. Here are some browser specific examples:
+
+```js run
+// toStringTag for the environment-specific object and class:
+alert( window[Symbol.toStringTag]); // Window
+alert( XMLHttpRequest.prototype[Symbol.toStringTag] ); // XMLHttpRequest
+
+alert( {}.toString.call(window) ); // [object Window]
+alert( {}.toString.call(new XMLHttpRequest()) ); // [object XMLHttpRequest]
+```
+
+As you can see, the result is exactly `Symbol.toStringTag` (if exists), wrapped into `[object ...]`.
+
+At the end we have "typeof on steroids" that not only works for primitive data types, but also for built-in objects and even can be customized.
+
+We can use `{}.toString.call` instead of `instanceof` for built-in objects when we want to get the type as a string rather than just to check.
+
+## Summary
+
+Let's summarize the type-checking methods that we know:
+
+| | works for | returns |
+|---------------|-------------|---------------|
+| `typeof` | primitives | string |
+| `{}.toString` | primitives, built-in objects, objects with `Symbol.toStringTag` | string |
+| `instanceof` | objects | true/false |
+
+As we can see, `{}.toString` is technically a "more advanced" `typeof`.
+
+And `instanceof` operator really shines when we are working with a class hierarchy and want to check for the class taking into account inheritance.
diff --git a/1-js/09-classes/06-instanceof/instanceof.svg b/1-js/09-classes/06-instanceof/instanceof.svg
new file mode 100644
index 0000000000..d63b03a8a2
--- /dev/null
+++ b/1-js/09-classes/06-instanceof/instanceof.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/09-classes/07-mixins/article.md b/1-js/09-classes/07-mixins/article.md
new file mode 100644
index 0000000000..526b832efa
--- /dev/null
+++ b/1-js/09-classes/07-mixins/article.md
@@ -0,0 +1,208 @@
+# Mixins
+
+In JavaScript we can only inherit from a single object. There can be only one `[[Prototype]]` for an object. And a class may extend only one other class.
+
+But sometimes that feels limiting. For instance, we have a class `StreetSweeper` and a class `Bicycle`, and want to make their mix: a `StreetSweepingBicycle`.
+
+Or we have a class `User` and a class `EventEmitter` that implements event generation, and we'd like to add the functionality of `EventEmitter` to `User`, so that our users can emit events.
+
+There's a concept that can help here, called "mixins".
+
+As defined in Wikipedia, a [mixin](https://en.wikipedia.org/wiki/Mixin) is a class containing methods that can be used by other classes without a need to inherit from it.
+
+In other words, a *mixin* provides methods that implement a certain behavior, but we do not use it alone, we use it to add the behavior to other classes.
+
+## A mixin example
+
+The simplest way to implement a mixin in JavaScript is to make an object with useful methods, so that we can easily merge them into a prototype of any class.
+
+For instance here the mixin `sayHiMixin` is used to add some "speech" for `User`:
+
+```js run
+*!*
+// mixin
+*/!*
+let sayHiMixin = {
+ sayHi() {
+ alert(`Hello ${this.name}`);
+ },
+ sayBye() {
+ alert(`Bye ${this.name}`);
+ }
+};
+
+*!*
+// usage:
+*/!*
+class User {
+ constructor(name) {
+ this.name = name;
+ }
+}
+
+// copy the methods
+Object.assign(User.prototype, sayHiMixin);
+
+// now User can say hi
+new User("Dude").sayHi(); // Hello Dude!
+```
+
+There's no inheritance, but a simple method copying. So `User` may inherit from another class and also include the mixin to "mix-in" the additional methods, like this:
+
+```js
+class User extends Person {
+ // ...
+}
+
+Object.assign(User.prototype, sayHiMixin);
+```
+
+Mixins can make use of inheritance inside themselves.
+
+For instance, here `sayHiMixin` inherits from `sayMixin`:
+
+```js run
+let sayMixin = {
+ say(phrase) {
+ alert(phrase);
+ }
+};
+
+let sayHiMixin = {
+ __proto__: sayMixin, // (or we could use Object.setPrototypeOf to set the prototype here)
+
+ sayHi() {
+ *!*
+ // call parent method
+ */!*
+ super.say(`Hello ${this.name}`); // (*)
+ },
+ sayBye() {
+ super.say(`Bye ${this.name}`); // (*)
+ }
+};
+
+class User {
+ constructor(name) {
+ this.name = name;
+ }
+}
+
+// copy the methods
+Object.assign(User.prototype, sayHiMixin);
+
+// now User can say hi
+new User("Dude").sayHi(); // Hello Dude!
+```
+
+Please note that the call to the parent method `super.say()` from `sayHiMixin` (at lines labelled with `(*)`) looks for the method in the prototype of that mixin, not the class.
+
+Here's the diagram (see the right part):
+
+
+
+That's because methods `sayHi` and `sayBye` were initially created in `sayHiMixin`. So even though they got copied, their `[[HomeObject]]` internal property references `sayHiMixin`, as shown in the picture above.
+
+As `super` looks for parent methods in `[[HomeObject]].[[Prototype]]`, that means it searches `sayHiMixin.[[Prototype]]`.
+
+## EventMixin
+
+Now let's make a mixin for real life.
+
+An important feature of many browser objects (for instance) is that they can generate events. Events are a great way to "broadcast information" to anyone who wants it. So let's make a mixin that allows us to easily add event-related functions to any class/object.
+
+- The mixin will provide a method `.trigger(name, [...data])` to "generate an event" when something important happens to it. The `name` argument is a name of the event, optionally followed by additional arguments with event data.
+- Also the method `.on(name, handler)` that adds `handler` function as the listener to events with the given name. It will be called when an event with the given `name` triggers, and get the arguments from the `.trigger` call.
+- ...And the method `.off(name, handler)` that removes the `handler` listener.
+
+After adding the mixin, an object `user` will be able to generate an event `"login"` when the visitor logs in. And another object, say, `calendar` may want to listen for such events to load the calendar for the logged-in person.
+
+Or, a `menu` can generate the event `"select"` when a menu item is selected, and other objects may assign handlers to react on that event. And so on.
+
+Here's the code:
+
+```js run
+let eventMixin = {
+ /**
+ * Subscribe to event, usage:
+ * menu.on('select', function(item) { ... }
+ */
+ on(eventName, handler) {
+ if (!this._eventHandlers) this._eventHandlers = {};
+ if (!this._eventHandlers[eventName]) {
+ this._eventHandlers[eventName] = [];
+ }
+ this._eventHandlers[eventName].push(handler);
+ },
+
+ /**
+ * Cancel the subscription, usage:
+ * menu.off('select', handler)
+ */
+ off(eventName, handler) {
+ let handlers = this._eventHandlers?.[eventName];
+ if (!handlers) return;
+ for (let i = 0; i < handlers.length; i++) {
+ if (handlers[i] === handler) {
+ handlers.splice(i--, 1);
+ }
+ }
+ },
+
+ /**
+ * Generate an event with the given name and data
+ * this.trigger('select', data1, data2);
+ */
+ trigger(eventName, ...args) {
+ if (!this._eventHandlers?.[eventName]) {
+ return; // no handlers for that event name
+ }
+
+ // call the handlers
+ this._eventHandlers[eventName].forEach(handler => handler.apply(this, args));
+ }
+};
+```
+
+
+- `.on(eventName, handler)` -- assigns function `handler` to run when the event with that name occurs. Technically, there's an `_eventHandlers` property that stores an array of handlers for each event name, and it just adds it to the list.
+- `.off(eventName, handler)` -- removes the function from the handlers list.
+- `.trigger(eventName, ...args)` -- generates the event: all handlers from `_eventHandlers[eventName]` are called, with a list of arguments `...args`.
+
+Usage:
+
+```js run
+// Make a class
+class Menu {
+ choose(value) {
+ this.trigger("select", value);
+ }
+}
+// Add the mixin with event-related methods
+Object.assign(Menu.prototype, eventMixin);
+
+let menu = new Menu();
+
+// add a handler, to be called on selection:
+*!*
+menu.on("select", value => alert(`Value selected: ${value}`));
+*/!*
+
+// triggers the event => the handler above runs and shows:
+// Value selected: 123
+menu.choose("123");
+```
+
+Now, if we'd like any code to react to a menu selection, we can listen for it with `menu.on(...)`.
+
+And `eventMixin` mixin makes it easy to add such behavior to as many classes as we'd like, without interfering with the inheritance chain.
+
+## Summary
+
+*Mixin* -- is a generic object-oriented programming term: a class that contains methods for other classes.
+
+Some other languages allow multiple inheritance. JavaScript does not support multiple inheritance, but mixins can be implemented by copying methods into prototype.
+
+We can use mixins as a way to augment a class by adding multiple behaviors, like event-handling as we have seen above.
+
+Mixins may become a point of conflict if they accidentally overwrite existing class methods. So generally one should think well about the naming methods of a mixin, to minimize the probability of that happening.
diff --git a/1-js/09-classes/07-mixins/head.html b/1-js/09-classes/07-mixins/head.html
new file mode 100644
index 0000000000..20e3a63547
--- /dev/null
+++ b/1-js/09-classes/07-mixins/head.html
@@ -0,0 +1,43 @@
+
diff --git a/1-js/09-classes/07-mixins/mixin-inheritance.svg b/1-js/09-classes/07-mixins/mixin-inheritance.svg
new file mode 100644
index 0000000000..1fdc223936
--- /dev/null
+++ b/1-js/09-classes/07-mixins/mixin-inheritance.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/09-classes/index.md b/1-js/09-classes/index.md
new file mode 100644
index 0000000000..87846ef6ba
--- /dev/null
+++ b/1-js/09-classes/index.md
@@ -0,0 +1 @@
+# Classes
diff --git a/1-js/10-error-handling/1-try-catch/1-finally-or-code-after/solution.md b/1-js/10-error-handling/1-try-catch/1-finally-or-code-after/solution.md
new file mode 100644
index 0000000000..ec0dabc9a6
--- /dev/null
+++ b/1-js/10-error-handling/1-try-catch/1-finally-or-code-after/solution.md
@@ -0,0 +1,47 @@
+The difference becomes obvious when we look at the code inside a function.
+
+The behavior is different if there's a "jump out" of `try...catch`.
+
+For instance, when there's a `return` inside `try...catch`. The `finally` clause works in case of *any* exit from `try...catch`, even via the `return` statement: right after `try...catch` is done, but before the calling code gets the control.
+
+```js run
+function f() {
+ try {
+ alert('start');
+*!*
+ return "result";
+*/!*
+ } catch (err) {
+ /// ...
+ } finally {
+ alert('cleanup!');
+ }
+}
+
+f(); // cleanup!
+```
+
+...Or when there's a `throw`, like here:
+
+```js run
+function f() {
+ try {
+ alert('start');
+ throw new Error("an error");
+ } catch (err) {
+ // ...
+ if("can't handle the error") {
+*!*
+ throw err;
+*/!*
+ }
+
+ } finally {
+ alert('cleanup!')
+ }
+}
+
+f(); // cleanup!
+```
+
+It's `finally` that guarantees the cleanup here. If we just put the code at the end of `f`, it wouldn't run in these situations.
diff --git a/1-js/10-error-handling/1-try-catch/1-finally-or-code-after/task.md b/1-js/10-error-handling/1-try-catch/1-finally-or-code-after/task.md
new file mode 100644
index 0000000000..b6dc813261
--- /dev/null
+++ b/1-js/10-error-handling/1-try-catch/1-finally-or-code-after/task.md
@@ -0,0 +1,38 @@
+importance: 5
+
+---
+
+# Finally or just the code?
+
+Compare the two code fragments.
+
+1. The first one uses `finally` to execute the code after `try...catch`:
+
+ ```js
+ try {
+ work work
+ } catch (err) {
+ handle errors
+ } finally {
+ *!*
+ cleanup the working space
+ */!*
+ }
+ ```
+2. The second fragment puts the cleaning right after `try...catch`:
+
+ ```js
+ try {
+ work work
+ } catch (err) {
+ handle errors
+ }
+
+ *!*
+ cleanup the working space
+ */!*
+ ```
+
+We definitely need the cleanup after the work, doesn't matter if there was an error or not.
+
+Is there an advantage here in using `finally` or both code fragments are equal? If there is such an advantage, then give an example when it matters.
diff --git a/1-js/10-error-handling/1-try-catch/article.md b/1-js/10-error-handling/1-try-catch/article.md
new file mode 100644
index 0000000000..cad2e1a3e7
--- /dev/null
+++ b/1-js/10-error-handling/1-try-catch/article.md
@@ -0,0 +1,675 @@
+# Error handling, "try...catch"
+
+No matter how great we are at programming, sometimes our scripts have errors. They may occur because of our mistakes, an unexpected user input, an erroneous server response, and for a thousand other reasons.
+
+Usually, a script "dies" (immediately stops) in case of an error, printing it to console.
+
+But there's a syntax construct `try...catch` that allows us to "catch" errors so the script can, instead of dying, do something more reasonable.
+
+## The "try...catch" syntax
+
+The `try...catch` construct has two main blocks: `try`, and then `catch`:
+
+```js
+try {
+
+ // code...
+
+} catch (err) {
+
+ // error handling
+
+}
+```
+
+It works like this:
+
+1. First, the code in `try {...}` is executed.
+2. If there were no errors, then `catch (err)` is ignored: the execution reaches the end of `try` and goes on, skipping `catch`.
+3. If an error occurs, then the `try` execution is stopped, and control flows to the beginning of `catch (err)`. The `err` variable (we can use any name for it) will contain an error object with details about what happened.
+
+
+
+So, an error inside the `try {...}` block does not kill the script -- we have a chance to handle it in `catch`.
+
+Let's look at some examples.
+
+- An errorless example: shows `alert` `(1)` and `(2)`:
+
+ ```js run
+ try {
+
+ alert('Start of try runs'); // *!*(1) <--*/!*
+
+ // ...no errors here
+
+ alert('End of try runs'); // *!*(2) <--*/!*
+
+ } catch (err) {
+
+ alert('Catch is ignored, because there are no errors'); // (3)
+
+ }
+ ```
+- An example with an error: shows `(1)` and `(3)`:
+
+ ```js run
+ try {
+
+ alert('Start of try runs'); // *!*(1) <--*/!*
+
+ *!*
+ lalala; // error, variable is not defined!
+ */!*
+
+ alert('End of try (never reached)'); // (2)
+
+ } catch (err) {
+
+ alert(`Error has occurred!`); // *!*(3) <--*/!*
+
+ }
+ ```
+
+
+````warn header="`try...catch` only works for runtime errors"
+For `try...catch` to work, the code must be runnable. In other words, it should be valid JavaScript.
+
+It won't work if the code is syntactically wrong, for instance it has unmatched curly braces:
+
+```js run
+try {
+ {{{{{{{{{{{{
+} catch (err) {
+ alert("The engine can't understand this code, it's invalid");
+}
+```
+
+The JavaScript engine first reads the code, and then runs it. The errors that occur on the reading phase are called "parse-time" errors and are unrecoverable (from inside that code). That's because the engine can't understand the code.
+
+So, `try...catch` can only handle errors that occur in valid code. Such errors are called "runtime errors" or, sometimes, "exceptions".
+````
+
+
+````warn header="`try...catch` works synchronously"
+If an exception happens in "scheduled" code, like in `setTimeout`, then `try...catch` won't catch it:
+
+```js run
+try {
+ setTimeout(function() {
+ noSuchVariable; // script will die here
+ }, 1000);
+} catch (err) {
+ alert( "won't work" );
+}
+```
+
+That's because the function itself is executed later, when the engine has already left the `try...catch` construct.
+
+To catch an exception inside a scheduled function, `try...catch` must be inside that function:
+```js run
+setTimeout(function() {
+ try {
+ noSuchVariable; // try...catch handles the error!
+ } catch {
+ alert( "error is caught here!" );
+ }
+}, 1000);
+```
+````
+
+## Error object
+
+When an error occurs, JavaScript generates an object containing the details about it. The object is then passed as an argument to `catch`:
+
+```js
+try {
+ // ...
+} catch (err) { // <-- the "error object", could use another word instead of err
+ // ...
+}
+```
+
+For all built-in errors, the error object has two main properties:
+
+`name`
+: Error name. For instance, for an undefined variable that's `"ReferenceError"`.
+
+`message`
+: Textual message about error details.
+
+There are other non-standard properties available in most environments. One of most widely used and supported is:
+
+`stack`
+: Current call stack: a string with information about the sequence of nested calls that led to the error. Used for debugging purposes.
+
+For instance:
+
+```js run untrusted
+try {
+*!*
+ lalala; // error, variable is not defined!
+*/!*
+} catch (err) {
+ alert(err.name); // ReferenceError
+ alert(err.message); // lalala is not defined
+ alert(err.stack); // ReferenceError: lalala is not defined at (...call stack)
+
+ // Can also show an error as a whole
+ // The error is converted to string as "name: message"
+ alert(err); // ReferenceError: lalala is not defined
+}
+```
+
+## Optional "catch" binding
+
+[recent browser=new]
+
+If we don't need error details, `catch` may omit it:
+
+```js
+try {
+ // ...
+} catch { // <-- without (err)
+ // ...
+}
+```
+
+## Using "try...catch"
+
+Let's explore a real-life use case of `try...catch`.
+
+As we already know, JavaScript supports the [JSON.parse(str)](mdn:js/JSON/parse) method to read JSON-encoded values.
+
+Usually it's used to decode data received over the network, from the server or another source.
+
+We receive it and call `JSON.parse` like this:
+
+```js run
+let json = '{"name":"John", "age": 30}'; // data from the server
+
+*!*
+let user = JSON.parse(json); // convert the text representation to JS object
+*/!*
+
+// now user is an object with properties from the string
+alert( user.name ); // John
+alert( user.age ); // 30
+```
+
+You can find more detailed information about JSON in the chapter.
+
+**If `json` is malformed, `JSON.parse` generates an error, so the script "dies".**
+
+Should we be satisfied with that? Of course not!
+
+This way, if something's wrong with the data, the visitor will never know that (unless they open the developer console). And people really don't like when something "just dies" without any error message.
+
+Let's use `try...catch` to handle the error:
+
+```js run
+let json = "{ bad json }";
+
+try {
+
+*!*
+ let user = JSON.parse(json); // <-- when an error occurs...
+*/!*
+ alert( user.name ); // doesn't work
+
+} catch (err) {
+*!*
+ // ...the execution jumps here
+ alert( "Our apologies, the data has errors, we'll try to request it one more time." );
+ alert( err.name );
+ alert( err.message );
+*/!*
+}
+```
+
+Here we use the `catch` block only to show the message, but we can do much more: send a new network request, suggest an alternative to the visitor, send information about the error to a logging facility, ... . All much better than just dying.
+
+## Throwing our own errors
+
+What if `json` is syntactically correct, but doesn't have a required `name` property?
+
+Like this:
+
+```js run
+let json = '{ "age": 30 }'; // incomplete data
+
+try {
+
+ let user = JSON.parse(json); // <-- no errors
+*!*
+ alert( user.name ); // no name!
+*/!*
+
+} catch (err) {
+ alert( "doesn't execute" );
+}
+```
+
+Here `JSON.parse` runs normally, but the absence of `name` is actually an error for us.
+
+To unify error handling, we'll use the `throw` operator.
+
+### "Throw" operator
+
+The `throw` operator generates an error.
+
+The syntax is:
+
+```js
+throw
+```
+
+Technically, we can use anything as an error object. That may be even a primitive, like a number or a string, but it's better to use objects, preferably with `name` and `message` properties (to stay somewhat compatible with built-in errors).
+
+JavaScript has many built-in constructors for standard errors: `Error`, `SyntaxError`, `ReferenceError`, `TypeError` and others. We can use them to create error objects as well.
+
+Their syntax is:
+
+```js
+let error = new Error(message);
+// or
+let error = new SyntaxError(message);
+let error = new ReferenceError(message);
+// ...
+```
+
+For built-in errors (not for any objects, just for errors), the `name` property is exactly the name of the constructor. And `message` is taken from the argument.
+
+For instance:
+
+```js run
+let error = new Error("Things happen o_O");
+
+alert(error.name); // Error
+alert(error.message); // Things happen o_O
+```
+
+Let's see what kind of error `JSON.parse` generates:
+
+```js run
+try {
+ JSON.parse("{ bad json o_O }");
+} catch (err) {
+*!*
+ alert(err.name); // SyntaxError
+*/!*
+ alert(err.message); // Unexpected token b in JSON at position 2
+}
+```
+
+As we can see, that's a `SyntaxError`.
+
+And in our case, the absence of `name` is an error, as users must have a `name`.
+
+So let's throw it:
+
+```js run
+let json = '{ "age": 30 }'; // incomplete data
+
+try {
+
+ let user = JSON.parse(json); // <-- no errors
+
+ if (!user.name) {
+*!*
+ throw new SyntaxError("Incomplete data: no name"); // (*)
+*/!*
+ }
+
+ alert( user.name );
+
+} catch (err) {
+ alert( "JSON Error: " + err.message ); // JSON Error: Incomplete data: no name
+}
+```
+
+In the line `(*)`, the `throw` operator generates a `SyntaxError` with the given `message`, the same way as JavaScript would generate it itself. The execution of `try` immediately stops and the control flow jumps into `catch`.
+
+Now `catch` became a single place for all error handling: both for `JSON.parse` and other cases.
+
+## Rethrowing
+
+In the example above we use `try...catch` to handle incorrect data. But is it possible that *another unexpected error* occurs within the `try {...}` block? Like a programming error (variable is not defined) or something else, not just this "incorrect data" thing.
+
+For example:
+
+```js run
+let json = '{ "age": 30 }'; // incomplete data
+
+try {
+ user = JSON.parse(json); // <-- forgot to put "let" before user
+
+ // ...
+} catch (err) {
+ alert("JSON Error: " + err); // JSON Error: ReferenceError: user is not defined
+ // (no JSON Error actually)
+}
+```
+
+Of course, everything's possible! Programmers do make mistakes. Even in open-source utilities used by millions for decades -- suddenly a bug may be discovered that leads to terrible hacks.
+
+In our case, `try...catch` is placed to catch "incorrect data" errors. But by its nature, `catch` gets *all* errors from `try`. Here it gets an unexpected error, but still shows the same `"JSON Error"` message. That's wrong and also makes the code more difficult to debug.
+
+To avoid such problems, we can employ the "rethrowing" technique. The rule is simple:
+
+**Catch should only process errors that it knows and "rethrow" all others.**
+
+The "rethrowing" technique can be explained in more detail as:
+
+1. Catch gets all errors.
+2. In the `catch (err) {...}` block we analyze the error object `err`.
+3. If we don't know how to handle it, we do `throw err`.
+
+Usually, we can check the error type using the `instanceof` operator:
+
+```js run
+try {
+ user = { /*...*/ };
+} catch (err) {
+*!*
+ if (err instanceof ReferenceError) {
+*/!*
+ alert('ReferenceError'); // "ReferenceError" for accessing an undefined variable
+ }
+}
+```
+
+We can also get the error class name from `err.name` property. All native errors have it. Another option is to read `err.constructor.name`.
+
+In the code below, we use rethrowing so that `catch` only handles `SyntaxError`:
+
+```js run
+let json = '{ "age": 30 }'; // incomplete data
+try {
+
+ let user = JSON.parse(json);
+
+ if (!user.name) {
+ throw new SyntaxError("Incomplete data: no name");
+ }
+
+*!*
+ blabla(); // unexpected error
+*/!*
+
+ alert( user.name );
+
+} catch (err) {
+
+*!*
+ if (err instanceof SyntaxError) {
+ alert( "JSON Error: " + err.message );
+ } else {
+ throw err; // rethrow (*)
+ }
+*/!*
+
+}
+```
+
+The error throwing on line `(*)` from inside `catch` block "falls out" of `try...catch` and can be either caught by an outer `try...catch` construct (if it exists), or it kills the script.
+
+So the `catch` block actually handles only errors that it knows how to deal with and "skips" all others.
+
+The example below demonstrates how such errors can be caught by one more level of `try...catch`:
+
+```js run
+function readData() {
+ let json = '{ "age": 30 }';
+
+ try {
+ // ...
+*!*
+ blabla(); // error!
+*/!*
+ } catch (err) {
+ // ...
+ if (!(err instanceof SyntaxError)) {
+*!*
+ throw err; // rethrow (don't know how to deal with it)
+*/!*
+ }
+ }
+}
+
+try {
+ readData();
+} catch (err) {
+*!*
+ alert( "External catch got: " + err ); // caught it!
+*/!*
+}
+```
+
+Here `readData` only knows how to handle `SyntaxError`, while the outer `try...catch` knows how to handle everything.
+
+## try...catch...finally
+
+Wait, that's not all.
+
+The `try...catch` construct may have one more code clause: `finally`.
+
+If it exists, it runs in all cases:
+
+- after `try`, if there were no errors,
+- after `catch`, if there were errors.
+
+The extended syntax looks like this:
+
+```js
+*!*try*/!* {
+ ... try to execute the code ...
+} *!*catch*/!* (err) {
+ ... handle errors ...
+} *!*finally*/!* {
+ ... execute always ...
+}
+```
+
+Try running this code:
+
+```js run
+try {
+ alert( 'try' );
+ if (confirm('Make an error?')) BAD_CODE();
+} catch (err) {
+ alert( 'catch' );
+} finally {
+ alert( 'finally' );
+}
+```
+
+The code has two ways of execution:
+
+1. If you answer "Yes" to "Make an error?", then `try -> catch -> finally`.
+2. If you say "No", then `try -> finally`.
+
+The `finally` clause is often used when we start doing something and want to finalize it in any case of outcome.
+
+For instance, we want to measure the time that a Fibonacci numbers function `fib(n)` takes. Naturally, we can start measuring before it runs and finish afterwards. But what if there's an error during the function call? In particular, the implementation of `fib(n)` in the code below returns an error for negative or non-integer numbers.
+
+The `finally` clause is a great place to finish the measurements no matter what.
+
+Here `finally` guarantees that the time will be measured correctly in both situations -- in case of a successful execution of `fib` and in case of an error in it:
+
+```js run
+let num = +prompt("Enter a positive integer number?", 35)
+
+let diff, result;
+
+function fib(n) {
+ if (n < 0 || Math.trunc(n) != n) {
+ throw new Error("Must not be negative, and also an integer.");
+ }
+ return n <= 1 ? n : fib(n - 1) + fib(n - 2);
+}
+
+let start = Date.now();
+
+try {
+ result = fib(num);
+} catch (err) {
+ result = 0;
+*!*
+} finally {
+ diff = Date.now() - start;
+}
+*/!*
+
+alert(result || "error occurred");
+
+alert( `execution took ${diff}ms` );
+```
+
+You can check by running the code with entering `35` into `prompt` -- it executes normally, `finally` after `try`. And then enter `-1` -- there will be an immediate error, and the execution will take `0ms`. Both measurements are done correctly.
+
+In other words, the function may finish with `return` or `throw`, that doesn't matter. The `finally` clause executes in both cases.
+
+
+```smart header="Variables are local inside `try...catch...finally`"
+Please note that `result` and `diff` variables in the code above are declared *before* `try...catch`.
+
+Otherwise, if we declared `let` in `try` block, it would only be visible inside of it.
+```
+
+````smart header="`finally` and `return`"
+The `finally` clause works for *any* exit from `try...catch`. That includes an explicit `return`.
+
+In the example below, there's a `return` in `try`. In this case, `finally` is executed just before the control returns to the outer code.
+
+```js run
+function func() {
+
+ try {
+*!*
+ return 1;
+*/!*
+
+ } catch (err) {
+ /* ... */
+ } finally {
+*!*
+ alert( 'finally' );
+*/!*
+ }
+}
+
+alert( func() ); // first works alert from finally, and then this one
+```
+````
+
+````smart header="`try...finally`"
+
+The `try...finally` construct, without `catch` clause, is also useful. We apply it when we don't want to handle errors here (let them fall through), but want to be sure that processes that we started are finalized.
+
+```js
+function func() {
+ // start doing something that needs completion (like measurements)
+ try {
+ // ...
+ } finally {
+ // complete that thing even if all dies
+ }
+}
+```
+In the code above, an error inside `try` always falls out, because there's no `catch`. But `finally` works before the execution flow leaves the function.
+````
+
+## Global catch
+
+```warn header="Environment-specific"
+The information from this section is not a part of the core JavaScript.
+```
+
+Let's imagine we've got a fatal error outside of `try...catch`, and the script died. Like a programming error or some other terrible thing.
+
+Is there a way to react on such occurrences? We may want to log the error, show something to the user (normally they don't see error messages), etc.
+
+There is none in the specification, but environments usually provide it, because it's really useful. For instance, Node.js has [`process.on("uncaughtException")`](https://nodejs.org/api/process.html#process_event_uncaughtexception) for that. And in the browser we can assign a function to the special [window.onerror](mdn:api/GlobalEventHandlers/onerror) property, that will run in case of an uncaught error.
+
+The syntax:
+
+```js
+window.onerror = function(message, url, line, col, error) {
+ // ...
+};
+```
+
+`message`
+: Error message.
+
+`url`
+: URL of the script where error happened.
+
+`line`, `col`
+: Line and column numbers where error happened.
+
+`error`
+: Error object.
+
+For instance:
+
+```html run untrusted refresh height=1
+
+```
+
+The role of the global handler `window.onerror` is usually not to recover the script execution -- that's probably impossible in case of programming errors, but to send the error message to developers.
+
+There are also web-services that provide error-logging for such cases, like or .
+
+They work like this:
+
+1. We register at the service and get a piece of JS (or a script URL) from them to insert on pages.
+2. That JS script sets a custom `window.onerror` function.
+3. When an error occurs, it sends a network request about it to the service.
+4. We can log in to the service web interface and see errors.
+
+## Summary
+
+The `try...catch` construct allows to handle runtime errors. It literally allows to "try" running the code and "catch" errors that may occur in it.
+
+The syntax is:
+
+```js
+try {
+ // run this code
+} catch (err) {
+ // if an error happened, then jump here
+ // err is the error object
+} finally {
+ // do in any case after try/catch
+}
+```
+
+There may be no `catch` section or no `finally`, so shorter constructs `try...catch` and `try...finally` are also valid.
+
+Error objects have following properties:
+
+- `message` -- the human-readable error message.
+- `name` -- the string with error name (error constructor name).
+- `stack` (non-standard, but well-supported) -- the stack at the moment of error creation.
+
+If an error object is not needed, we can omit it by using `catch {` instead of `catch (err) {`.
+
+We can also generate our own errors using the `throw` operator. Technically, the argument of `throw` can be anything, but usually it's an error object inheriting from the built-in `Error` class. More on extending errors in the next chapter.
+
+*Rethrowing* is a very important pattern of error handling: a `catch` block usually expects and knows how to handle the particular error type, so it should rethrow errors it doesn't know.
+
+Even if we don't have `try...catch`, most environments allow us to setup a "global" error handler to catch errors that "fall out". In-browser, that's `window.onerror`.
diff --git a/1-js/10-error-handling/1-try-catch/try-catch-flow.svg b/1-js/10-error-handling/1-try-catch/try-catch-flow.svg
new file mode 100644
index 0000000000..2c0d71348c
--- /dev/null
+++ b/1-js/10-error-handling/1-try-catch/try-catch-flow.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/1-js/10-error-handling/2-custom-errors/1-format-error/solution.md b/1-js/10-error-handling/2-custom-errors/1-format-error/solution.md
new file mode 100644
index 0000000000..754e68f9a4
--- /dev/null
+++ b/1-js/10-error-handling/2-custom-errors/1-format-error/solution.md
@@ -0,0 +1,16 @@
+```js run untrusted
+class FormatError extends SyntaxError {
+ constructor(message) {
+ super(message);
+ this.name = this.constructor.name;
+ }
+}
+
+let err = new FormatError("formatting error");
+
+alert( err.message ); // formatting error
+alert( err.name ); // FormatError
+alert( err.stack ); // stack
+
+alert( err instanceof SyntaxError ); // true
+```
diff --git a/1-js/08-error-handling/2-custom-errors/1-format-error/task.md b/1-js/10-error-handling/2-custom-errors/1-format-error/task.md
similarity index 100%
rename from 1-js/08-error-handling/2-custom-errors/1-format-error/task.md
rename to 1-js/10-error-handling/2-custom-errors/1-format-error/task.md
diff --git a/1-js/10-error-handling/2-custom-errors/article.md b/1-js/10-error-handling/2-custom-errors/article.md
new file mode 100644
index 0000000000..d28b07439b
--- /dev/null
+++ b/1-js/10-error-handling/2-custom-errors/article.md
@@ -0,0 +1,330 @@
+# Custom errors, extending Error
+
+When we develop something, we often need our own error classes to reflect specific things that may go wrong in our tasks. For errors in network operations we may need `HttpError`, for database operations `DbError`, for searching operations `NotFoundError` and so on.
+
+Our errors should support basic error properties like `message`, `name` and, preferably, `stack`. But they also may have other properties of their own, e.g. `HttpError` objects may have a `statusCode` property with a value like `404` or `403` or `500`.
+
+JavaScript allows to use `throw` with any argument, so technically our custom error classes don't need to inherit from `Error`. But if we inherit, then it becomes possible to use `obj instanceof Error` to identify error objects. So it's better to inherit from it.
+
+As the application grows, our own errors naturally form a hierarchy. For instance, `HttpTimeoutError` may inherit from `HttpError`, and so on.
+
+## Extending Error
+
+As an example, let's consider a function `readUser(json)` that should read JSON with user data.
+
+Here's an example of how a valid `json` may look:
+```js
+let json = `{ "name": "John", "age": 30 }`;
+```
+
+Internally, we'll use `JSON.parse`. If it receives malformed `json`, then it throws `SyntaxError`. But even if `json` is syntactically correct, that doesn't mean that it's a valid user, right? It may miss the necessary data. For instance, it may not have `name` and `age` properties that are essential for our users.
+
+Our function `readUser(json)` will not only read JSON, but check ("validate") the data. If there are no required fields, or the format is wrong, then that's an error. And that's not a `SyntaxError`, because the data is syntactically correct, but another kind of error. We'll call it `ValidationError` and create a class for it. An error of that kind should also carry the information about the offending field.
+
+Our `ValidationError` class should inherit from the `Error` class.
+
+The `Error` class is built-in, but here's its approximate code so we can understand what we're extending:
+
+```js
+// The "pseudocode" for the built-in Error class defined by JavaScript itself
+class Error {
+ constructor(message) {
+ this.message = message;
+ this.name = "Error"; // (different names for different built-in error classes)
+ this.stack = ; // non-standard, but most environments support it
+ }
+}
+```
+
+Now let's inherit `ValidationError` from it and try it in action:
+
+```js run
+*!*
+class ValidationError extends Error {
+*/!*
+ constructor(message) {
+ super(message); // (1)
+ this.name = "ValidationError"; // (2)
+ }
+}
+
+function test() {
+ throw new ValidationError("Whoops!");
+}
+
+try {
+ test();
+} catch(err) {
+ alert(err.message); // Whoops!
+ alert(err.name); // ValidationError
+ alert(err.stack); // a list of nested calls with line numbers for each
+}
+```
+
+Please note: in the line `(1)` we call the parent constructor. JavaScript requires us to call `super` in the child constructor, so that's obligatory. The parent constructor sets the `message` property.
+
+The parent constructor also sets the `name` property to `"Error"`, so in the line `(2)` we reset it to the right value.
+
+Let's try to use it in `readUser(json)`:
+
+```js run
+class ValidationError extends Error {
+ constructor(message) {
+ super(message);
+ this.name = "ValidationError";
+ }
+}
+
+// Usage
+function readUser(json) {
+ let user = JSON.parse(json);
+
+ if (!user.age) {
+ throw new ValidationError("No field: age");
+ }
+ if (!user.name) {
+ throw new ValidationError("No field: name");
+ }
+
+ return user;
+}
+
+// Working example with try..catch
+
+try {
+ let user = readUser('{ "age": 25 }');
+} catch (err) {
+ if (err instanceof ValidationError) {
+*!*
+ alert("Invalid data: " + err.message); // Invalid data: No field: name
+*/!*
+ } else if (err instanceof SyntaxError) { // (*)
+ alert("JSON Syntax Error: " + err.message);
+ } else {
+ throw err; // unknown error, rethrow it (**)
+ }
+}
+```
+
+The `try..catch` block in the code above handles both our `ValidationError` and the built-in `SyntaxError` from `JSON.parse`.
+
+Please take a look at how we use `instanceof` to check for the specific error type in the line `(*)`.
+
+We could also look at `err.name`, like this:
+
+```js
+// ...
+// instead of (err instanceof SyntaxError)
+} else if (err.name == "SyntaxError") { // (*)
+// ...
+```
+
+The `instanceof` version is much better, because in the future we are going to extend `ValidationError`, make subtypes of it, like `PropertyRequiredError`. And `instanceof` check will continue to work for new inheriting classes. So that's future-proof.
+
+Also it's important that if `catch` meets an unknown error, then it rethrows it in the line `(**)`. The `catch` block only knows how to handle validation and syntax errors, other kinds (caused by a typo in the code or other unknown reasons) should fall through.
+
+## Further inheritance
+
+The `ValidationError` class is very generic. Many things may go wrong. The property may be absent or it may be in a wrong format (like a string value for `age` instead of a number). Let's make a more concrete class `PropertyRequiredError`, exactly for absent properties. It will carry additional information about the property that's missing.
+
+```js run
+class ValidationError extends Error {
+ constructor(message) {
+ super(message);
+ this.name = "ValidationError";
+ }
+}
+
+*!*
+class PropertyRequiredError extends ValidationError {
+ constructor(property) {
+ super("No property: " + property);
+ this.name = "PropertyRequiredError";
+ this.property = property;
+ }
+}
+*/!*
+
+// Usage
+function readUser(json) {
+ let user = JSON.parse(json);
+
+ if (!user.age) {
+ throw new PropertyRequiredError("age");
+ }
+ if (!user.name) {
+ throw new PropertyRequiredError("name");
+ }
+
+ return user;
+}
+
+// Working example with try..catch
+
+try {
+ let user = readUser('{ "age": 25 }');
+} catch (err) {
+ if (err instanceof ValidationError) {
+*!*
+ alert("Invalid data: " + err.message); // Invalid data: No property: name
+ alert(err.name); // PropertyRequiredError
+ alert(err.property); // name
+*/!*
+ } else if (err instanceof SyntaxError) {
+ alert("JSON Syntax Error: " + err.message);
+ } else {
+ throw err; // unknown error, rethrow it
+ }
+}
+```
+
+The new class `PropertyRequiredError` is easy to use: we only need to pass the property name: `new PropertyRequiredError(property)`. The human-readable `message` is generated by the constructor.
+
+Please note that `this.name` in `PropertyRequiredError` constructor is again assigned manually. That may become a bit tedious -- to assign `this.name = ` in every custom error class. We can avoid it by making our own "basic error" class that assigns `this.name = this.constructor.name`. And then inherit all our custom errors from it.
+
+Let's call it `MyError`.
+
+Here's the code with `MyError` and other custom error classes, simplified:
+
+```js run
+class MyError extends Error {
+ constructor(message) {
+ super(message);
+*!*
+ this.name = this.constructor.name;
+*/!*
+ }
+}
+
+class ValidationError extends MyError { }
+
+class PropertyRequiredError extends ValidationError {
+ constructor(property) {
+ super("No property: " + property);
+ this.property = property;
+ }
+}
+
+// name is correct
+alert( new PropertyRequiredError("field").name ); // PropertyRequiredError
+```
+
+Now custom errors are much shorter, especially `ValidationError`, as we got rid of the `"this.name = ..."` line in the constructor.
+
+## Wrapping exceptions
+
+The purpose of the function `readUser` in the code above is "to read the user data". There may occur different kinds of errors in the process. Right now we have `SyntaxError` and `ValidationError`, but in the future `readUser` function may grow and probably generate other kinds of errors.
+
+The code which calls `readUser` should handle these errors. Right now it uses multiple `if`s in the `catch` block, that check the class and handle known errors and rethrow the unknown ones.
+
+The scheme is like this:
+
+```js
+try {
+ ...
+ readUser() // the potential error source
+ ...
+} catch (err) {
+ if (err instanceof ValidationError) {
+ // handle validation errors
+ } else if (err instanceof SyntaxError) {
+ // handle syntax errors
+ } else {
+ throw err; // unknown error, rethrow it
+ }
+}
+```
+
+In the code above we can see two types of errors, but there can be more.
+
+If the `readUser` function generates several kinds of errors, then we should ask ourselves: do we really want to check for all error types one-by-one every time?
+
+Often the answer is "No": we'd like to be "one level above all that". We just want to know if there was a "data reading error" -- why exactly it happened is often irrelevant (the error message describes it). Or, even better, we'd like to have a way to get the error details, but only if we need to.
+
+The technique that we describe here is called "wrapping exceptions".
+
+1. We'll make a new class `ReadError` to represent a generic "data reading" error.
+2. The function `readUser` will catch data reading errors that occur inside it, such as `ValidationError` and `SyntaxError`, and generate a `ReadError` instead.
+3. The `ReadError` object will keep the reference to the original error in its `cause` property.
+
+Then the code that calls `readUser` will only have to check for `ReadError`, not for every kind of data reading errors. And if it needs more details of an error, it can check its `cause` property.
+
+Here's the code that defines `ReadError` and demonstrates its use in `readUser` and `try..catch`:
+
+```js run
+class ReadError extends Error {
+ constructor(message, cause) {
+ super(message);
+ this.cause = cause;
+ this.name = 'ReadError';
+ }
+}
+
+class ValidationError extends Error { /*...*/ }
+class PropertyRequiredError extends ValidationError { /* ... */ }
+
+function validateUser(user) {
+ if (!user.age) {
+ throw new PropertyRequiredError("age");
+ }
+
+ if (!user.name) {
+ throw new PropertyRequiredError("name");
+ }
+}
+
+function readUser(json) {
+ let user;
+
+ try {
+ user = JSON.parse(json);
+ } catch (err) {
+*!*
+ if (err instanceof SyntaxError) {
+ throw new ReadError("Syntax Error", err);
+ } else {
+ throw err;
+ }
+*/!*
+ }
+
+ try {
+ validateUser(user);
+ } catch (err) {
+*!*
+ if (err instanceof ValidationError) {
+ throw new ReadError("Validation Error", err);
+ } else {
+ throw err;
+ }
+*/!*
+ }
+
+}
+
+try {
+ readUser('{bad json}');
+} catch (e) {
+ if (e instanceof ReadError) {
+*!*
+ alert(e);
+ // Original error: SyntaxError: Unexpected token b in JSON at position 1
+ alert("Original error: " + e.cause);
+*/!*
+ } else {
+ throw e;
+ }
+}
+```
+
+In the code above, `readUser` works exactly as described -- catches syntax and validation errors and throws `ReadError` errors instead (unknown errors are rethrown as usual).
+
+So the outer code checks `instanceof ReadError` and that's it. No need to list all possible error types.
+
+The approach is called "wrapping exceptions", because we take "low level" exceptions and "wrap" them into `ReadError` that is more abstract. It is widely used in object-oriented programming.
+
+## Summary
+
+- We can inherit from `Error` and other built-in error classes normally. We just need to take care of the `name` property and don't forget to call `super`.
+- We can use `instanceof` to check for particular errors. It also works with inheritance. But sometimes we have an error object coming from a 3rd-party library and there's no easy way to get its class. Then `name` property can be used for such checks.
+- Wrapping exceptions is a widespread technique: a function handles low-level exceptions and creates higher-level errors instead of various low-level ones. Low-level exceptions sometimes become properties of that object like `err.cause` in the examples above, but that's not strictly required.
diff --git a/1-js/08-error-handling/index.md b/1-js/10-error-handling/index.md
similarity index 100%
rename from 1-js/08-error-handling/index.md
rename to 1-js/10-error-handling/index.md
diff --git a/1-js/11-async/01-callbacks/article.md b/1-js/11-async/01-callbacks/article.md
new file mode 100644
index 0000000000..57115a9098
--- /dev/null
+++ b/1-js/11-async/01-callbacks/article.md
@@ -0,0 +1,312 @@
+
+
+# Introduction: callbacks
+
+```warn header="We use browser methods in examples here"
+To demonstrate the use of callbacks, promises and other abstract concepts, we'll be using some browser methods: specifically, loading scripts and performing simple document manipulations.
+
+If you're not familiar with these methods, and their usage in the examples is confusing, you may want to read a few chapters from the [next part](/document) of the tutorial.
+
+Although, we'll try to make things clear anyway. There won't be anything really complex browser-wise.
+```
+
+Many functions are provided by JavaScript host environments that allow you to schedule *asynchronous* actions. In other words, actions that we initiate now, but they finish later.
+
+For instance, one such function is the `setTimeout` function.
+
+There are other real-world examples of asynchronous actions, e.g. loading scripts and modules (we'll cover them in later chapters).
+
+Take a look at the function `loadScript(src)`, that loads a script with the given `src`:
+
+```js
+function loadScript(src) {
+ // creates a
+
+
+
+