` 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 increase 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/solution.md b/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/solution.md
index 19a072014b..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 `calls.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 9ebb7abfca..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
@@ -27,4 +27,4 @@ for (let args of work.calls) {
}
```
-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
+![](debounce.svg)
-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="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 547f336c53..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 their 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 3f86b0d307..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
@@ -6,9 +6,9 @@ JavaScript gives exceptional flexibility when dealing with functions. They can b
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:
@@ -23,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.
@@ -49,21 +49,18 @@ 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:
-![](decorator-makecaching-wrapper.png)
+![](decorator-makecaching-wrapper.svg)
-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.
@@ -78,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(); // (*)
}
@@ -152,8 +149,8 @@ let user = { name: "John" };
let admin = { name: "Admin" };
// use call to pass different objects as "this"
-sayHi.call( user ); // this = John
-sayHi.call( admin ); // this = Admin
+sayHi.call( user ); // John
+sayHi.call( admin ); // Admin
```
And here we use `call` to call `say` with the given context and phrase:
@@ -170,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() {
@@ -214,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.
@@ -231,9 +226,7 @@ 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:
@@ -241,85 +234,11 @@ There are many solutions possible:
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 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:
-
-```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.
+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)`.
-When an external code calls such `wrapper`, it is indistinguishable 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 = {
@@ -340,7 +259,7 @@ function cachingDecorator(func, hash) {
}
*!*
- let result = func.apply(this, arguments); // (**)
+ let result = func.call(this, ...arguments); // (**)
*/!*
cache.set(key, result);
@@ -358,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]
@@ -386,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:
@@ -414,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?
@@ -432,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 needs 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:
@@ -450,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 f93690963c..6d65e7dd10 100644
--- a/1-js/06-advanced-functions/10-bind/article.md
+++ b/1-js/06-advanced-functions/10-bind/article.md
@@ -5,13 +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.
+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`:
@@ -37,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 = {
@@ -83,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.
@@ -98,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`.
@@ -159,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.
@@ -178,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`"
@@ -193,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 f8b83d7a20..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(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/11-currying-partials/article.md b/1-js/06-advanced-functions/11-currying-partials/article.md
deleted file mode 100644
index e866f38a75..0000000000
--- a/1-js/06-advanced-functions/11-currying-partials/article.md
+++ /dev/null
@@ -1,296 +0,0 @@
-libs:
- - lodash
-
----
-
-# Currying and partials
-
-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
-*!*
-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] 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 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 1ade1a4192..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,9 +2,9 @@
Let's revisit arrow functions.
-Arrow functions are not just a "shorthand" for writing small stuff.
+Arrow functions are not just a "shorthand" for writing small stuff. They have some very specific and useful features.
-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:
@@ -14,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"
@@ -52,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);
});
*/!*
}
@@ -87,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);
};
}
@@ -118,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 do 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 b189660664..0000000000
--- a/1-js/07-object-oriented-programming/01-property-descriptors/article.md
+++ /dev/null
@@ -1,318 +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 a more complex and tunable thing.
-
-## 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 anytime.
-
-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 they apply their 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 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 `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 `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 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 all property 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.
-
-Another difference is that `for..in` ignores symbolic properties, but `Object.getOwnPropertyDescriptors` returns *all* property descriptors including symbolic 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)](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 fa4d2216d5..0000000000
--- a/1-js/07-object-oriented-programming/02-property-accessors/article.md
+++ /dev/null
@@ -1,237 +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.
-
-## 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); // name, surname
-```
-
-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 002b24b8a2..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 `pockets.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 fad4b88607..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 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, 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 fa61cbc89d..0000000000
--- a/1-js/07-object-oriented-programming/03-prototype-inheritance/article.md
+++ /dev/null
@@ -1,250 +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.
-
-## [[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":
-
-![prototype](object-prototype-empty.png)
-
-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):
-
-![](proto-animal-rabbit.png)
-
-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:
-
-![](proto-animal-rabbit-walk.png)
-
-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)
-```
-
-![](proto-animal-rabbit-chain.png)
-
-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:
-
-![](proto-animal-rabbit-walk-2.png)
-
-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:
-
-![](proto-animal-rabbit-walk-3.png)
-
-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 d4b4538507..0000000000
--- a/1-js/07-object-oriented-programming/04-function-prototype/article.md
+++ /dev/null
@@ -1,174 +0,0 @@
-# F.prototype
-
-In modern JavaScript we can set a prototype using `__proto__`, as described in the previous article. But it wasn't like that all the time.
-
-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.
-
-When a new object is created with `new F()`, the object's `[[Prototype]]` is set to `F.prototype`.
-
-In other words, if `F` has a `prototype` property with a value of the object type, then `new` operator uses it to set `[[Prototype]]` for the new object.
-
-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:
-
-![](proto-constructor-animal-rabbit.png)
-
-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 };
-*/
-```
-
-![](function-prototype-constructor.png)
-
-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)
-```
-
-![](rabbit-prototype-constructor.png)
-
-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 4777f356f8..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):
-
-![](object-prototype.png)
-
-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:
-
-![](object-prototype-1.png)
-
-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):
-
-![](native-prototypes-classes.png)
-
-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.
-
-
-![](native-prototypes-array-tostring.png)
-
-
-In-browser tools like Chrome developer console also show inheritance (may need to use `console.dir` for built-in objects):
-
-![](console_dir_array.png)
-
-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 e253e8af76..0000000000
--- a/1-js/07-object-oriented-programming/06-prototype-methods/article.md
+++ /dev/null
@@ -1,253 +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`.
-
-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 an object cloning more powerful than copying properties in `for..in`:
-
-```js
-// fully identical shallow clone of obj
-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
-
-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`:
-
-![](object-prototype-2.png)
-
-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`):
-
-![](object-prototype-null.png)
-
-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:
-
-![](rabbit-animal-object.png)
-
-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 92b521c192..0000000000
--- a/1-js/07-object-oriented-programming/08-class-patterns/article.md
+++ /dev/null
@@ -1,240 +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 from the theory of object-oriented programming. The definition is cited above, and it's language-independent.
-
-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.
-
-
-## 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, age:17
-```
-
-In this code variables `name`, `birthday` and the function `calcAge()` are internal, *private* to the object. They are only visible from inside of it.
-
-On 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, age:17
-```
-
-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 are 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, age:17
-```
-
-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");
-```
-
-![](rabbit-animal-independent-1.png)
-
-...And `Animal`:
-
-```js
-function Animal(name) {
- this.name = name;
-}
-
-Animal.prototype.eat = function() {
- alert(`${this.name} eats.`);
-};
-
-let animal = new Animal("My animal");
-```
-
-![](rabbit-animal-independent-2.png)
-
-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 of 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:
-
-![](class-inheritance-rabbit-animal.png)
-
-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:
-
-![](class-inheritance-rabbit-animal-2.png)
-
-## 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 e63d7d7844..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 3d1be9ccef..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/article.md b/1-js/07-object-oriented-programming/09-class/article.md
deleted file mode 100644
index 71878ae35b..0000000000
--- a/1-js/07-object-oriented-programming/09-class/article.md
+++ /dev/null
@@ -1,355 +0,0 @@
-
-# Classes
-
-The "class" construct allows to define prototype-based classes with a clean, nice-looking syntax.
-
-## The "class" syntax
-
-The `class` syntax is versatile, we'll start with 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. Just please note that methods in a class do not have a comma between them. Novice developers sometimes forget it and put a comma between class methods, and things don't work. That's not a literal object, but a class syntax.
-
-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 methods listed in the definition into `User.prototype`. Here, it includes `sayHi` and the `constructor`.
-
-Here's the code to dig into the class and see 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 what `class User` creates:
-
-![](class-user.png)
-
-
-
-So `class` is a special syntax to define a constructor together with its prototype methods.
-
-...But not only that. There are minor tweaks here and there:
-
-Constructors require `new`
-: Unlike a regular function, a class `constructor` 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'
-```
-
-Different string output
-: 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.
-
-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.
-
-Classes have a default `constructor() {}`
-: If there's no `constructor` in the `class` construct, then an empty function is generated, same as if we had written `constructor() {}`.
-
-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 is too short.");
- return;
- }
- this._name = value;
- }
-
-}
-
-let user = new User("John");
-alert(user.name); // John
-
-user = new User(""); // Name too short.
-```
-
-Internally, getters and setters are also created on the `User` prototype, like this:
-
-```js
-Object.defineProperties(User.prototype, {
- name: {
- get() {
- return this._name
- },
- set(name) {
- // ...
- }
- }
-});
-```
-
-### Only methods
-
-Unlike object literals, no `property:value` assignments are allowed inside `class`. There may be only methods and getters/setters. There is some work going on in the specification to lift that limitation, but it's not yet there.
-
-If we really need to put a non-function value into the prototype, then we can alter `prototype` manually, 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. Such properties will be shared among all objects of the class.
-
-An "in-class" alternative is 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 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 makeClass(phrase) {
-*!*
- // declare a class and return it
- return class {
- sayHi() {
- alert(phrase);
- };
- };
-*/!*
-}
-
-let User = makeClass("Hello");
-
-new User().sayHi(); // Hello
-```
-
-That's quite normal if we recall that `class` is just a special form of a 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
-// "Named Class Expression" (alas, no such term, but that's what's going on)
-let User = class *!*MyClass*/!* {
- sayHi() {
- alert(MyClass); // MyClass is visible only inside the class
- }
-};
-
-new User().sayHi(); // works, shows MyClass definition
-
-alert(MyClass); // error, MyClass not visible outside of the class
-```
-
-## Static methods
-
-We can also assign methods to the class function, not to its `"prototype"`. Such methods are called *static*.
-
-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 to implement functions that belong to the class, but not to any 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. It's not a method of an article, but rather of the whole class.
-
-Another example would be a so-called "factory" method. Imagine, we need few ways to create an article:
-
-1. Create by given parameters (`title`, `date` etc).
-2. Create an empty article with today's date.
-3. ...
-
-The first way can be implemented by the constructor. And for the second one we can make a static method of the class.
-
-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("Today's digest", new Date());
- }
-*/!*
-}
-
-let article = Article.createTodays();
-
-alert( article.title ); // Todays 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:
-Article.remove({id: 12345});
-```
-
-## Summary
-
-The basic class syntax looks like this:
-
-```js
-class MyClass {
- constructor(...) {
- // ...
- }
- method1(...) {}
- method2(...) {}
- get something(...) {}
- set something(...) {}
- static staticMethod(..) {}
- // ...
-}
-```
-
-The value of `MyClass` is a function provided as `constructor`. If there's no `constructor`, then an empty function.
-
-In any case, methods listed in the class declaration become members of its `prototype`, with the exception of static methods that are written into the function itself and callable as `MyClass.staticMethod()`. Static methods are used when we need a function bound to a class, but not to any object of that class.
-
-In the next chapter we'll learn more about classes, including inheritance.
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 c1483aa365..0000000000
--- a/1-js/07-object-oriented-programming/10-class-inheritance/3-class-extend-object/solution.md
+++ /dev/null
@@ -1,81 +0,0 @@
-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 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 `Rabbit` now provides access to 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` 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:
-
-![](rabbit-extends-object.png)
-
-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 ca6628edf1..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 `hasOwnProperty` etc.
-
-For instance:
-
-```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
-*/!*
-```
-
-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') ); // true
-```
diff --git a/1-js/07-object-oriented-programming/10-class-inheritance/animal-rabbit-extends.png b/1-js/07-object-oriented-programming/10-class-inheritance/animal-rabbit-extends.png
deleted file mode 100644
index 2db88f3663..0000000000
Binary files a/1-js/07-object-oriented-programming/10-class-inheritance/animal-rabbit-extends.png and /dev/null differ
diff --git a/1-js/07-object-oriented-programming/10-class-inheritance/animal-rabbit-extends@2x.png b/1-js/07-object-oriented-programming/10-class-inheritance/animal-rabbit-extends@2x.png
deleted file mode 100644
index 9539fe9ec6..0000000000
Binary files a/1-js/07-object-oriented-programming/10-class-inheritance/animal-rabbit-extends@2x.png and /dev/null differ
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 2c44e5eadd..0000000000
--- a/1-js/07-object-oriented-programming/10-class-inheritance/article.md
+++ /dev/null
@@ -1,575 +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 `{..}`.
-
-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.
-
-![](animal-rabbit-extends.png)
-
-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 it gets 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 the `method`? Naturally, we need to take the `method` from the prototype of the current object. How, technically, we (or a JavaScript engine) can do it?
-
-Maybe we can get the method from `[[Prototype]]` of `this`, as `this.__proto__.method`? Unfortunately, that doesn'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() {
-*!*
- // 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:
-
-![](this-super-loop.png)
-
-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.**
-
-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`.
-
-
-![](animal-rabbit-static.png)
-
-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`.
-
-### No static inheritance in built-ins
-
-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`:
-
-![](object-date-inheritance.png)
-
-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 637d179398..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 af7b443bcb..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 702c9e6b20..0000000000
--- a/1-js/07-object-oriented-programming/11-instanceof/article.md
+++ /dev/null
@@ -1,211 +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.
-
-## 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`:
-
-![](instanceof.png)
-
-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 the 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 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 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 bb51395e69..0000000000
--- a/1-js/07-object-oriented-programming/13-mixins/article.md
+++ /dev/null
@@ -1,205 +0,0 @@
-# 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, I have a class `StreetSweeper` and a class `Bicycle`, and want to make a `StreetSweepingBicycle`.
-
-Or, talking about programming, we have a class `Renderer` that implements templating and a class `EventEmitter` that implements event handling, and want to merge these functionalities together with a class `Page`, to make a page that can use templates and 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 that contains methods for use by other classes without having to be the parent class of those other classes.
-
-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 make 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 extend some other 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.create 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` looks for the method in the prototype of that mixin, not the class.
-
-![](mixin-inheritance.png)
-
-That's because methods from `sayHiMixin` have `[[HomeObject]]` set to it. So `super` actually means `sayHiMixin.__proto__`, not `User.__proto__`.
-
-## EventMixin
-
-Now let's make a mixin for 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 "listen" to such events.
-
-An event must have a name and, optionally, bundle some additional data.
-
-For instance, an object `user` can generate an event `"login"` when the visitor logs in. And another object `calendar` may want to receive 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 want to get that information and react on that event.
-
-Events is a way to "share information" with anyone who wants it. They can be useful in any class, so let's make a mixin for them:
-
-```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 eabfb7423f..0000000000
--- a/1-js/08-error-handling/1-try-catch/article.md
+++ /dev/null
@@ -1,660 +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.
-
-## 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.
-
-![](try-catch-flow.png)
-
-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 curly braces:
-
-```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 "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 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 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 (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 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 (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 absence 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 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 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
- // (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 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 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 (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`"
-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 (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 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 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 d7d61166dd..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 its `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":
+
+![prototype](object-prototype-empty.svg)
+
+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):
+
+![](proto-animal-rabbit.svg)
+
+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:
+
+![](proto-animal-rabbit-walk.svg)
+
+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)
+```
+
+![](proto-animal-rabbit-chain.svg)
+
+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:
+
+![](proto-animal-rabbit-walk-2.svg)
+
+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:
+
+![](proto-animal-rabbit-walk-3.svg)
+
+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:
+
+![](rabbit-animal-object.svg)
+
+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:
+
+![](proto-constructor-animal-rabbit.svg)
+
+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 };
+*/
+```
+
+![](function-prototype-constructor.svg)
+
+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)
+```
+
+![](rabbit-prototype-constructor.svg)
+
+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:
+
+![](object-prototype.svg)
+
+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:
+
+![](object-prototype-1.svg)
+
+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):
+
+![](native-prototypes-classes.svg)
+
+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.
+
+
+![](native-prototypes-array-tostring.svg)
+
+
+In-browser tools like Chrome developer console also show inheritance (`console.dir` may need to be used for built-in objects):
+
+![](console_dir_array.png)
+
+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..34b977e9f1
--- /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 an assignment 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`:
+
+![](object-prototype-2.svg)
+
+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`):
+
+![](object-prototype-null.svg)
+
+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:
+
+![](class-user.svg)
+
+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="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="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:
+
+![](rabbit-animal-independent-animal.svg)
+
+...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`.
+
+![](animal-rabbit-extends.svg)
+
+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:
+
+![](this-super-loop.svg)
+
+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:
+
+![](super-homeobject-wrong.svg)
+
+### 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:
+
+![](rabbit-extends-object.svg)
+
+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`.
+
+![](animal-rabbit-static.svg)
+
+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! :)
+
+![](coffee.jpg)
+
+But inside... (a picture from the repair manual)
+
+![](coffee-inside.jpg)
+
+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`:
+
+![](object-date-inheritance.svg)
+
+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`:
+
+![](instanceof.svg)
+
+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):
+
+![](mixin-inheritance.svg)
+
+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..bf548373ad
--- /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.
+
+![](try-catch-flow.svg)
+
+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
+
+
+
+