diff --git a/1-js/09-classes/01-class-patterns/1-inheritance-error-assign/solution.md b/1-js/09-classes/01-class-patterns/1-inheritance-error-assign/solution.md deleted file mode 100644 index 55f945ca5..000000000 --- a/1-js/09-classes/01-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/09-classes/01-class-patterns/1-inheritance-error-assign/task.md b/1-js/09-classes/01-class-patterns/1-inheritance-error-assign/task.md deleted file mode 100644 index ee486c3d6..000000000 --- a/1-js/09-classes/01-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/09-classes/01-class-patterns/2-rewrite-to-prototypes/solution.md b/1-js/09-classes/01-class-patterns/2-rewrite-to-prototypes/solution.md deleted file mode 100644 index 300b25d94..000000000 --- a/1-js/09-classes/01-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/09-classes/01-class-patterns/2-rewrite-to-prototypes/solution.view/clock.js b/1-js/09-classes/01-class-patterns/2-rewrite-to-prototypes/solution.view/clock.js deleted file mode 100644 index bdf7bb72d..000000000 --- a/1-js/09-classes/01-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) 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); -}; - -Clock.prototype.stop = function() { - clearInterval(this.timer); -}; - -Clock.prototype.start = function() { - this.render(); - this.timer = setInterval(() => this.render(), 1000); -}; diff --git a/1-js/09-classes/01-class-patterns/2-rewrite-to-prototypes/solution.view/index.html b/1-js/09-classes/01-class-patterns/2-rewrite-to-prototypes/solution.view/index.html deleted file mode 100644 index fdee13d01..000000000 --- a/1-js/09-classes/01-class-patterns/2-rewrite-to-prototypes/solution.view/index.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - Console clock - - - - - - - - - - diff --git a/1-js/09-classes/01-class-patterns/2-rewrite-to-prototypes/source.view/index.html b/1-js/09-classes/01-class-patterns/2-rewrite-to-prototypes/source.view/index.html deleted file mode 100644 index fdee13d01..000000000 --- a/1-js/09-classes/01-class-patterns/2-rewrite-to-prototypes/source.view/index.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - Console clock - - - - - - - - - - diff --git a/1-js/09-classes/01-class-patterns/2-rewrite-to-prototypes/task.md b/1-js/09-classes/01-class-patterns/2-rewrite-to-prototypes/task.md deleted file mode 100644 index 71131816b..000000000 --- a/1-js/09-classes/01-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/09-classes/01-class-patterns/article.md b/1-js/09-classes/01-class-patterns/article.md deleted file mode 100644 index ca120f71f..000000000 --- a/1-js/09-classes/01-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. People talk about "classes" meaning not only those defined with `class`, but also with these patterns. - -The `class` construct will be described in the next chapter, but in JavaScript it's a "syntax sugar" and an extension of the prototypal class pattern described 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/09-classes/01-class-patterns/rabbit-animal-independent-1.png b/1-js/09-classes/01-class-patterns/rabbit-animal-independent-1.png deleted file mode 100644 index f4a11d6c5..000000000 Binary files a/1-js/09-classes/01-class-patterns/rabbit-animal-independent-1.png and /dev/null differ diff --git a/1-js/09-classes/01-class-patterns/rabbit-animal-independent-1@2x.png b/1-js/09-classes/01-class-patterns/rabbit-animal-independent-1@2x.png deleted file mode 100644 index 60451263d..000000000 Binary files a/1-js/09-classes/01-class-patterns/rabbit-animal-independent-1@2x.png and /dev/null differ diff --git a/1-js/09-classes/01-class-patterns/rabbit-animal-independent-2.png b/1-js/09-classes/01-class-patterns/rabbit-animal-independent-2.png deleted file mode 100644 index 7dfee8176..000000000 Binary files a/1-js/09-classes/01-class-patterns/rabbit-animal-independent-2.png and /dev/null differ diff --git a/1-js/09-classes/01-class-patterns/rabbit-animal-independent-2@2x.png b/1-js/09-classes/01-class-patterns/rabbit-animal-independent-2@2x.png deleted file mode 100644 index 473c2d29e..000000000 Binary files a/1-js/09-classes/01-class-patterns/rabbit-animal-independent-2@2x.png and /dev/null differ diff --git a/1-js/09-classes/03-class-inheritance/2-clock-class-extended/source.view/clock.js b/1-js/09-classes/01-class/1-rewrite-to-class/_js.view/solution.js similarity index 91% rename from 1-js/09-classes/03-class-inheritance/2-clock-class-extended/source.view/clock.js rename to 1-js/09-classes/01-class/1-rewrite-to-class/_js.view/solution.js index d701c0cae..0b31cf334 100644 --- a/1-js/09-classes/03-class-inheritance/2-clock-class-extended/source.view/clock.js +++ b/1-js/09-classes/01-class/1-rewrite-to-class/_js.view/solution.js @@ -32,3 +32,7 @@ class Clock { 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-patterns/2-rewrite-to-prototypes/source.view/clock.js b/1-js/09-classes/01-class/1-rewrite-to-class/_js.view/source.js similarity index 90% rename from 1-js/09-classes/01-class-patterns/2-rewrite-to-prototypes/source.view/clock.js rename to 1-js/09-classes/01-class/1-rewrite-to-class/_js.view/source.js index c4bfaa0ff..f1749c8ba 100644 --- a/1-js/09-classes/01-class-patterns/2-rewrite-to-prototypes/source.view/clock.js +++ b/1-js/09-classes/01-class/1-rewrite-to-class/_js.view/source.js @@ -32,3 +32,6 @@ function Clock({ template }) { }; } + +let clock = new Clock({template: 'h:m:s'}); +clock.start(); diff --git a/1-js/09-classes/02-class/1-rewrite-to-class/solution.md b/1-js/09-classes/01-class/1-rewrite-to-class/solution.md similarity index 100% rename from 1-js/09-classes/02-class/1-rewrite-to-class/solution.md rename to 1-js/09-classes/01-class/1-rewrite-to-class/solution.md diff --git a/1-js/09-classes/02-class/1-rewrite-to-class/task.md b/1-js/09-classes/01-class/1-rewrite-to-class/task.md similarity index 53% rename from 1-js/09-classes/02-class/1-rewrite-to-class/task.md rename to 1-js/09-classes/01-class/1-rewrite-to-class/task.md index a29d347f5..05365e410 100644 --- a/1-js/09-classes/02-class/1-rewrite-to-class/task.md +++ b/1-js/09-classes/01-class/1-rewrite-to-class/task.md @@ -4,6 +4,6 @@ importance: 5 # Rewrite to class -Rewrite the `Clock` class from prototypes to the modern "class" syntax. +The `Clock` class is written in functional style. Rewrite it 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 000000000..018545b10 --- /dev/null +++ b/1-js/09-classes/01-class/article.md @@ -0,0 +1,368 @@ + +# Classes + +```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 `new MyClass()` creates 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 `this.name` to it. + +...Then we can call 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 a 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 is we don't write such method). +3. Stores all methods, such as `sayHi`, in `User.prototype`. + +Afterwards, for new objects, when we call a method, it's taken from the prototype, just as described in the chapter . So `new User` object has access to class methods. + +We can illustrate the result of `class User` as: + +![](class-user.png) + +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); // alert(this.name); + +// there are exactly two methods in the prototype +alert(Object.getOwnPropertyNames(User.prototype)); // constructor, sayHi +``` + +## Not just a syntax sugar + +Sometimes people say that `class` is a "syntax sugar" in JavaScript, because we could actually declare the same without `class` keyword at all: + +```js run +// rewriting class User in pure functions + +// 1. Create constructor function +function User(name) { + this.name = name; +} +// any 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 syntax sugar to define a constructor together with its prototype methods. + +Although, there are important differences. + +1. First, a function created by `class` is labelled by a special internal property `[[FunctionKind]]:"classConstructor"`. So it's not entirely the same as creating it manually. + + 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' + ``` + + 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 { ... } + ``` + +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. + + +Also, in addition to its basic operation, the `class` syntax brings many other features with it which 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 or may not have a name. + +If a class expression has a name, it's visible inside the 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 +``` + + +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, other shorthands + +Classes also include getters/setters, generators, 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 too short. +``` + +Internally, getters and setters are created on `User.prototype`, like this: + +```js +Object.defineProperties(User.prototype, { + name: { + get() { + return this._name + }, + set(name) { + // ... + } + } +}); +``` + +Here's an example with computed properties: + +```js run +function f() { return "sayHi"; } + +class User { + [f()]() { + alert("Hello"); + } + +} + +new User().sayHi(); +``` + +For a generator method, similarly, prepend it with `*`. + +## Class properties + +```warn header="Old browsers may need a polyfill" +Class-level properties are a recent addition to the language. +``` + +In the example above, `User` only had methods. Let's add a property: + +```js run +class User { + name = "Anonymous"; + + sayHi() { + alert(`Hello, ${this.name}!`); + } +} + +new User().sayHi(); +``` + +The property is not placed into `User.prototype`. Instead, it is created by `new`, separately for every object. So, the property will never be shared between different objects of the same class. + + +## Summary + +JavaScript provides many ways to create a class. + +First, as per the general object-oriented terminology, a class is something that provides "object templates", allows to create same-structured objects. + +When we say "a class", that doesn't necessary means the `class` keyword. + +This is a class: + +```js +function User(name) { + this.sayHi = function() { + alert(name); + } +} +``` + +...But in most cases `class` keyword is used, as it provides great syntax and many additional features. + +The basic class syntax looks like this: + +```js +class MyClass { + prop = value; // field + + constructor(...) { // constructor + // ... + } + + method(...) {} // method + + get something(...) {} // getter method + set something(...) {} // setter method + + [Symbol.iterator]() {} // method with computed name/symbol name + // ... +} +``` + +`MyClass` is technically a function, while methods 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/02-class/class-user.png b/1-js/09-classes/01-class/class-user.png similarity index 100% rename from 1-js/09-classes/02-class/class-user.png rename to 1-js/09-classes/01-class/class-user.png diff --git a/1-js/09-classes/02-class/class-user@2x.png b/1-js/09-classes/01-class/class-user@2x.png similarity index 100% rename from 1-js/09-classes/02-class/class-user@2x.png rename to 1-js/09-classes/01-class/class-user@2x.png diff --git a/1-js/09-classes/03-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/09-classes/03-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/09-classes/03-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/09-classes/03-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/03-class-inheritance/2-clock-class-extended/solution.md b/1-js/09-classes/02-class-inheritance/2-clock-class-extended/solution.md similarity index 100% rename from 1-js/09-classes/03-class-inheritance/2-clock-class-extended/solution.md rename to 1-js/09-classes/02-class-inheritance/2-clock-class-extended/solution.md diff --git a/1-js/09-classes/02-class/1-rewrite-to-class/solution.view/clock.js b/1-js/09-classes/02-class-inheritance/2-clock-class-extended/solution.view/clock.js similarity index 100% rename from 1-js/09-classes/02-class/1-rewrite-to-class/solution.view/clock.js rename to 1-js/09-classes/02-class-inheritance/2-clock-class-extended/solution.view/clock.js diff --git a/1-js/09-classes/03-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 similarity index 100% rename from 1-js/09-classes/03-class-inheritance/2-clock-class-extended/solution.view/extended-clock.js rename to 1-js/09-classes/02-class-inheritance/2-clock-class-extended/solution.view/extended-clock.js diff --git a/1-js/09-classes/03-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 similarity index 100% rename from 1-js/09-classes/03-class-inheritance/2-clock-class-extended/solution.view/index.html rename to 1-js/09-classes/02-class-inheritance/2-clock-class-extended/solution.view/index.html diff --git a/1-js/09-classes/03-class-inheritance/2-clock-class-extended/solution.view/clock.js b/1-js/09-classes/02-class-inheritance/2-clock-class-extended/source.view/clock.js similarity index 100% rename from 1-js/09-classes/03-class-inheritance/2-clock-class-extended/solution.view/clock.js rename to 1-js/09-classes/02-class-inheritance/2-clock-class-extended/source.view/clock.js diff --git a/1-js/09-classes/03-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 similarity index 100% rename from 1-js/09-classes/03-class-inheritance/2-clock-class-extended/source.view/index.html rename to 1-js/09-classes/02-class-inheritance/2-clock-class-extended/source.view/index.html diff --git a/1-js/09-classes/03-class-inheritance/2-clock-class-extended/task.md b/1-js/09-classes/02-class-inheritance/2-clock-class-extended/task.md similarity index 100% rename from 1-js/09-classes/03-class-inheritance/2-clock-class-extended/task.md rename to 1-js/09-classes/02-class-inheritance/2-clock-class-extended/task.md diff --git a/1-js/09-classes/03-class-inheritance/3-class-extend-object/rabbit-extends-object.png b/1-js/09-classes/02-class-inheritance/3-class-extend-object/rabbit-extends-object.png similarity index 100% rename from 1-js/09-classes/03-class-inheritance/3-class-extend-object/rabbit-extends-object.png rename to 1-js/09-classes/02-class-inheritance/3-class-extend-object/rabbit-extends-object.png diff --git a/1-js/09-classes/03-class-inheritance/3-class-extend-object/rabbit-extends-object@2x.png b/1-js/09-classes/02-class-inheritance/3-class-extend-object/rabbit-extends-object@2x.png similarity index 100% rename from 1-js/09-classes/03-class-inheritance/3-class-extend-object/rabbit-extends-object@2x.png rename to 1-js/09-classes/02-class-inheritance/3-class-extend-object/rabbit-extends-object@2x.png diff --git a/1-js/09-classes/03-class-inheritance/3-class-extend-object/solution.md b/1-js/09-classes/02-class-inheritance/3-class-extend-object/solution.md similarity index 100% rename from 1-js/09-classes/03-class-inheritance/3-class-extend-object/solution.md rename to 1-js/09-classes/02-class-inheritance/3-class-extend-object/solution.md diff --git a/1-js/09-classes/03-class-inheritance/3-class-extend-object/task.md b/1-js/09-classes/02-class-inheritance/3-class-extend-object/task.md similarity index 100% rename from 1-js/09-classes/03-class-inheritance/3-class-extend-object/task.md rename to 1-js/09-classes/02-class-inheritance/3-class-extend-object/task.md diff --git a/1-js/09-classes/02-class-inheritance/animal-rabbit-extends.png b/1-js/09-classes/02-class-inheritance/animal-rabbit-extends.png new file mode 100644 index 000000000..0d887dbc0 Binary files /dev/null and b/1-js/09-classes/02-class-inheritance/animal-rabbit-extends.png differ diff --git a/1-js/09-classes/02-class-inheritance/animal-rabbit-extends@2x.png b/1-js/09-classes/02-class-inheritance/animal-rabbit-extends@2x.png new file mode 100644 index 000000000..af09271a9 Binary files /dev/null and b/1-js/09-classes/02-class-inheritance/animal-rabbit-extends@2x.png differ diff --git a/1-js/09-classes/03-class-inheritance/article.md b/1-js/09-classes/02-class-inheritance/article.md similarity index 89% rename from 1-js/09-classes/03-class-inheritance/article.md rename to 1-js/09-classes/02-class-inheritance/article.md index 1541a9650..2a482143e 100644 --- a/1-js/09-classes/03-class-inheritance/article.md +++ b/1-js/09-classes/02-class-inheritance/article.md @@ -1,7 +1,53 @@ # Class inheritance -Classes can extend one another. There's a nice syntax, technically based on the prototypal inheritance. +Let's say we have two classes. + +`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} stopped.`); + } +} + +let animal = new Animal("My animal"); +``` + +![](rabbit-animal-independent-animal.png) + + +...And `Rabbit`: + +```js +class Rabbit extends Animal { + constructor(name) { + this.name = name; + } + hide() { + alert(`${this.name} hides!`); + } +} + +let rabbit = new Rabbit("My rabbit"); +``` + +![](rabbit-animal-independent-rabbit.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. To inherit from another class, we should specify `"extends"` and the parent class before the brackets `{..}`. @@ -9,22 +55,18 @@ 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.`); } - } *!* @@ -42,11 +84,15 @@ 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. +Now the `Rabbit` code became a bit shorter, as it uses `Animal` constructor by default, and it also can `run`, as animals do. + +Internally, `extends` keyword adds `[[Prototype]]` reference from `Rabbit.prototype` to `Animal.prototype`: ![](animal-rabbit-extends.png) -So now `rabbit` has access both to its own methods and to methods of `Animal`. +So, if a method is not found in `Rabbit.prototype`, JavaScript takes it from `Animal.prototype`. + +As we can recall from the chapter , JavaScript uses the same prototypal inheritance for build-in objects. E.g. `Date.prototype.[[Prototype]]` is `Object.prototype`, so dates have 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`. diff --git a/1-js/09-classes/03-class-inheritance/class-inheritance-array-object.png b/1-js/09-classes/02-class-inheritance/class-inheritance-array-object.png similarity index 100% rename from 1-js/09-classes/03-class-inheritance/class-inheritance-array-object.png rename to 1-js/09-classes/02-class-inheritance/class-inheritance-array-object.png diff --git a/1-js/09-classes/03-class-inheritance/class-inheritance-array-object@2x.png b/1-js/09-classes/02-class-inheritance/class-inheritance-array-object@2x.png similarity index 100% rename from 1-js/09-classes/03-class-inheritance/class-inheritance-array-object@2x.png rename to 1-js/09-classes/02-class-inheritance/class-inheritance-array-object@2x.png diff --git a/1-js/09-classes/01-class-patterns/class-inheritance-rabbit-animal-2.png b/1-js/09-classes/02-class-inheritance/class-inheritance-rabbit-animal-2.png similarity index 100% rename from 1-js/09-classes/01-class-patterns/class-inheritance-rabbit-animal-2.png rename to 1-js/09-classes/02-class-inheritance/class-inheritance-rabbit-animal-2.png diff --git a/1-js/09-classes/01-class-patterns/class-inheritance-rabbit-animal-2@2x.png b/1-js/09-classes/02-class-inheritance/class-inheritance-rabbit-animal-2@2x.png similarity index 100% rename from 1-js/09-classes/01-class-patterns/class-inheritance-rabbit-animal-2@2x.png rename to 1-js/09-classes/02-class-inheritance/class-inheritance-rabbit-animal-2@2x.png diff --git a/1-js/09-classes/01-class-patterns/class-inheritance-rabbit-animal.png b/1-js/09-classes/02-class-inheritance/class-inheritance-rabbit-animal.png similarity index 100% rename from 1-js/09-classes/01-class-patterns/class-inheritance-rabbit-animal.png rename to 1-js/09-classes/02-class-inheritance/class-inheritance-rabbit-animal.png diff --git a/1-js/09-classes/01-class-patterns/class-inheritance-rabbit-animal@2x.png b/1-js/09-classes/02-class-inheritance/class-inheritance-rabbit-animal@2x.png similarity index 100% rename from 1-js/09-classes/01-class-patterns/class-inheritance-rabbit-animal@2x.png rename to 1-js/09-classes/02-class-inheritance/class-inheritance-rabbit-animal@2x.png diff --git a/1-js/09-classes/03-class-inheritance/class-inheritance-rabbit-run-animal.png b/1-js/09-classes/02-class-inheritance/class-inheritance-rabbit-run-animal.png similarity index 100% rename from 1-js/09-classes/03-class-inheritance/class-inheritance-rabbit-run-animal.png rename to 1-js/09-classes/02-class-inheritance/class-inheritance-rabbit-run-animal.png diff --git a/1-js/09-classes/03-class-inheritance/class-inheritance-rabbit-run-animal@2x.png b/1-js/09-classes/02-class-inheritance/class-inheritance-rabbit-run-animal@2x.png similarity index 100% rename from 1-js/09-classes/03-class-inheritance/class-inheritance-rabbit-run-animal@2x.png rename to 1-js/09-classes/02-class-inheritance/class-inheritance-rabbit-run-animal@2x.png diff --git a/1-js/09-classes/02-class-inheritance/rabbit-animal-independent-animal.png b/1-js/09-classes/02-class-inheritance/rabbit-animal-independent-animal.png new file mode 100644 index 000000000..79351a754 Binary files /dev/null and b/1-js/09-classes/02-class-inheritance/rabbit-animal-independent-animal.png differ diff --git a/1-js/09-classes/02-class-inheritance/rabbit-animal-independent-animal@2x.png b/1-js/09-classes/02-class-inheritance/rabbit-animal-independent-animal@2x.png new file mode 100644 index 000000000..346574e0c Binary files /dev/null and b/1-js/09-classes/02-class-inheritance/rabbit-animal-independent-animal@2x.png differ diff --git a/1-js/09-classes/02-class-inheritance/rabbit-animal-independent-rabbit.png b/1-js/09-classes/02-class-inheritance/rabbit-animal-independent-rabbit.png new file mode 100644 index 000000000..3d3b78cca Binary files /dev/null and b/1-js/09-classes/02-class-inheritance/rabbit-animal-independent-rabbit.png differ diff --git a/1-js/09-classes/02-class-inheritance/rabbit-animal-independent-rabbit@2x.png b/1-js/09-classes/02-class-inheritance/rabbit-animal-independent-rabbit@2x.png new file mode 100644 index 000000000..a923d10e5 Binary files /dev/null and b/1-js/09-classes/02-class-inheritance/rabbit-animal-independent-rabbit@2x.png differ diff --git a/1-js/09-classes/03-class-inheritance/this-super-loop.png b/1-js/09-classes/02-class-inheritance/this-super-loop.png similarity index 100% rename from 1-js/09-classes/03-class-inheritance/this-super-loop.png rename to 1-js/09-classes/02-class-inheritance/this-super-loop.png diff --git a/1-js/09-classes/03-class-inheritance/this-super-loop@2x.png b/1-js/09-classes/02-class-inheritance/this-super-loop@2x.png similarity index 100% rename from 1-js/09-classes/03-class-inheritance/this-super-loop@2x.png rename to 1-js/09-classes/02-class-inheritance/this-super-loop@2x.png diff --git a/1-js/09-classes/02-class/1-rewrite-to-class/solution.view/index.html b/1-js/09-classes/02-class/1-rewrite-to-class/solution.view/index.html deleted file mode 100644 index fdee13d01..000000000 --- a/1-js/09-classes/02-class/1-rewrite-to-class/solution.view/index.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - Console clock - - - - - - - - - - diff --git a/1-js/09-classes/02-class/1-rewrite-to-class/source.view/clock.js b/1-js/09-classes/02-class/1-rewrite-to-class/source.view/clock.js deleted file mode 100644 index 537f7268c..000000000 --- a/1-js/09-classes/02-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) 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); -}; - -Clock.prototype.stop = function() { - clearInterval(this.timer); -}; - -Clock.prototype.start = function() { - this.render(); - this.timer = setInterval(() => this.render(), 1000); -}; diff --git a/1-js/09-classes/02-class/1-rewrite-to-class/source.view/index.html b/1-js/09-classes/02-class/1-rewrite-to-class/source.view/index.html deleted file mode 100644 index fdee13d01..000000000 --- a/1-js/09-classes/02-class/1-rewrite-to-class/source.view/index.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - Console clock - - - - - - - - - - diff --git a/1-js/09-classes/02-class/article.md b/1-js/09-classes/02-class/article.md deleted file mode 100644 index 74a6e8082..000000000 --- a/1-js/09-classes/02-class/article.md +++ /dev/null @@ -1,272 +0,0 @@ - -# Classes - -The "class" construct allows one to define prototype-based classes with a clean, nice-looking syntax. It also introduces great new features which are useful for object-oriented programming. - -## 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 here'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 these two examples are alike. Be sure to note that methods in a class do not have a comma between them. 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 syntactical sugar, no commas are required. - -## What is a class? - -So, what exactly is a `class`? We may think that it defines a new language-level entity, but that would be wrong. - -In Javascript, a class is a kind of function. - -The definition `class User {...}` creates a function under the same name and puts the methods into `User.prototype`. So the structure is similar. - -This is demonstrated in the following code, which you can run yourself: - -```js run -class User { - constructor(name) { this.name = name; } - sayHi() { alert(this.name); } -} - -*!* -// proof: User is a function -alert(typeof User); // function -*/!* - -*!* -// 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 -``` - -Abstractly, we can illustrate this process of `class User` creating a function as: - -![](class-user.png) - -`Class` is a special syntax to define a constructor together with its prototype methods. In addition to its basic operation, the `Class` syntax brings many other features with it which we'll explore later. - -## Class Expression - -Just like functions, classes can be defined inside another expression, passed around, returned etc. - -Here's a class-returning function - otherwise known as a "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 -``` - -## Differences between classes and functions - -Classes have some differences compared to regular functions: - -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, just as if we had written `constructor() {}`. - -Classes always `use strict` -: All code inside the class construct is automatically in strict mode. - - -## Getters/setters, other shorthands - -Classes also include getters/setters, generators, 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 too short. -``` - -Internally, getters and setters are created on `User.prototype`, like this: - -```js -Object.defineProperties(User.prototype, { - name: { - get() { - return this._name - }, - set(name) { - // ... - } - } -}); -``` - -Here's an example with computed properties: - -```js run -function f() { return "sayHi"; } - -class User { - [f()]() { - alert("Hello"); - } - -} - -new User().sayHi(); -``` - -For a generator method, similarly, prepend it with `*`. - -## Class properties - -```warn header="Old browsers may need a polyfill" -Class-level properties are a recent addition to the language. -``` - -In the example above, `User` only had methods. Let's add a property: - -```js run -class User { - name = "Anonymous"; - - sayHi() { - alert(`Hello, ${this.name}!`); - } -} - -new User().sayHi(); -``` - -The property is not placed into `User.prototype`. Instead, it is created by `new`, separately for every object. So, the property will never be shared between different objects of the same class. - - -## Summary - -The basic class syntax looks like this: - -```js -class MyClass { - prop = value; - - constructor(...) { - // ... - } - - method(...) {} - - get something(...) {} - set something(...) {} - - [Symbol.iterator]() {} - // ... -} -``` - -`MyClass` is technically a function, while methods 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/03-class-inheritance/animal-rabbit-extends.png b/1-js/09-classes/03-class-inheritance/animal-rabbit-extends.png deleted file mode 100644 index c9fadf778..000000000 Binary files a/1-js/09-classes/03-class-inheritance/animal-rabbit-extends.png and /dev/null differ diff --git a/1-js/09-classes/03-class-inheritance/animal-rabbit-extends@2x.png b/1-js/09-classes/03-class-inheritance/animal-rabbit-extends@2x.png deleted file mode 100644 index 95979c2f1..000000000 Binary files a/1-js/09-classes/03-class-inheritance/animal-rabbit-extends@2x.png and /dev/null differ diff --git a/1-js/09-classes/03-class-inheritance/class-inheritance-rabbit-animal.png b/1-js/09-classes/03-class-inheritance/class-inheritance-rabbit-animal.png deleted file mode 100644 index a6f8964e6..000000000 Binary files a/1-js/09-classes/03-class-inheritance/class-inheritance-rabbit-animal.png and /dev/null differ diff --git a/1-js/09-classes/03-class-inheritance/class-inheritance-rabbit-animal@2x.png b/1-js/09-classes/03-class-inheritance/class-inheritance-rabbit-animal@2x.png deleted file mode 100644 index 2e3f4d7ff..000000000 Binary files a/1-js/09-classes/03-class-inheritance/class-inheritance-rabbit-animal@2x.png and /dev/null differ diff --git a/1-js/09-classes/04-static-properties-methods/animal-rabbit-static.png b/1-js/09-classes/03-static-properties-methods/animal-rabbit-static.png similarity index 100% rename from 1-js/09-classes/04-static-properties-methods/animal-rabbit-static.png rename to 1-js/09-classes/03-static-properties-methods/animal-rabbit-static.png diff --git a/1-js/09-classes/04-static-properties-methods/animal-rabbit-static@2x.png b/1-js/09-classes/03-static-properties-methods/animal-rabbit-static@2x.png similarity index 100% rename from 1-js/09-classes/04-static-properties-methods/animal-rabbit-static@2x.png rename to 1-js/09-classes/03-static-properties-methods/animal-rabbit-static@2x.png diff --git a/1-js/09-classes/04-static-properties-methods/article.md b/1-js/09-classes/03-static-properties-methods/article.md similarity index 100% rename from 1-js/09-classes/04-static-properties-methods/article.md rename to 1-js/09-classes/03-static-properties-methods/article.md diff --git a/1-js/09-classes/05-private-protected-properties-methods/article.md b/1-js/09-classes/04-private-protected-properties-methods/article.md similarity index 100% rename from 1-js/09-classes/05-private-protected-properties-methods/article.md rename to 1-js/09-classes/04-private-protected-properties-methods/article.md diff --git a/1-js/09-classes/05-private-protected-properties-methods/coffee-inside.jpg b/1-js/09-classes/04-private-protected-properties-methods/coffee-inside.jpg similarity index 100% rename from 1-js/09-classes/05-private-protected-properties-methods/coffee-inside.jpg rename to 1-js/09-classes/04-private-protected-properties-methods/coffee-inside.jpg diff --git a/1-js/09-classes/05-private-protected-properties-methods/coffee.jpg b/1-js/09-classes/04-private-protected-properties-methods/coffee.jpg similarity index 100% rename from 1-js/09-classes/05-private-protected-properties-methods/coffee.jpg rename to 1-js/09-classes/04-private-protected-properties-methods/coffee.jpg diff --git a/1-js/09-classes/06-extend-natives/article.md b/1-js/09-classes/05-extend-natives/article.md similarity index 100% rename from 1-js/09-classes/06-extend-natives/article.md rename to 1-js/09-classes/05-extend-natives/article.md diff --git a/1-js/09-classes/06-extend-natives/object-date-inheritance.png b/1-js/09-classes/05-extend-natives/object-date-inheritance.png similarity index 100% rename from 1-js/09-classes/06-extend-natives/object-date-inheritance.png rename to 1-js/09-classes/05-extend-natives/object-date-inheritance.png diff --git a/1-js/09-classes/06-extend-natives/object-date-inheritance@2x.png b/1-js/09-classes/05-extend-natives/object-date-inheritance@2x.png similarity index 100% rename from 1-js/09-classes/06-extend-natives/object-date-inheritance@2x.png rename to 1-js/09-classes/05-extend-natives/object-date-inheritance@2x.png diff --git a/1-js/09-classes/07-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/09-classes/07-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/07-instanceof/1-strange-instanceof/task.md b/1-js/09-classes/06-instanceof/1-strange-instanceof/task.md similarity index 100% rename from 1-js/09-classes/07-instanceof/1-strange-instanceof/task.md rename to 1-js/09-classes/06-instanceof/1-strange-instanceof/task.md diff --git a/1-js/09-classes/07-instanceof/article.md b/1-js/09-classes/06-instanceof/article.md similarity index 100% rename from 1-js/09-classes/07-instanceof/article.md rename to 1-js/09-classes/06-instanceof/article.md diff --git a/1-js/09-classes/07-instanceof/instanceof.png b/1-js/09-classes/06-instanceof/instanceof.png similarity index 100% rename from 1-js/09-classes/07-instanceof/instanceof.png rename to 1-js/09-classes/06-instanceof/instanceof.png diff --git a/1-js/09-classes/07-instanceof/instanceof@2x.png b/1-js/09-classes/06-instanceof/instanceof@2x.png similarity index 100% rename from 1-js/09-classes/07-instanceof/instanceof@2x.png rename to 1-js/09-classes/06-instanceof/instanceof@2x.png diff --git a/1-js/09-classes/08-mixins/article.md b/1-js/09-classes/07-mixins/article.md similarity index 100% rename from 1-js/09-classes/08-mixins/article.md rename to 1-js/09-classes/07-mixins/article.md diff --git a/1-js/09-classes/08-mixins/head.html b/1-js/09-classes/07-mixins/head.html similarity index 100% rename from 1-js/09-classes/08-mixins/head.html rename to 1-js/09-classes/07-mixins/head.html diff --git a/1-js/09-classes/08-mixins/mixin-inheritance.png b/1-js/09-classes/07-mixins/mixin-inheritance.png similarity index 100% rename from 1-js/09-classes/08-mixins/mixin-inheritance.png rename to 1-js/09-classes/07-mixins/mixin-inheritance.png diff --git a/1-js/09-classes/08-mixins/mixin-inheritance@2x.png b/1-js/09-classes/07-mixins/mixin-inheritance@2x.png similarity index 100% rename from 1-js/09-classes/08-mixins/mixin-inheritance@2x.png rename to 1-js/09-classes/07-mixins/mixin-inheritance@2x.png diff --git a/figures.sketch b/figures.sketch index bcd3d5a25..c740ac577 100644 Binary files a/figures.sketch and b/figures.sketch differ