From 8b08f95ce09f0df1db768913d4baa976fc34a339 Mon Sep 17 00:00:00 2001 From: RedrockJS Date: Wed, 5 Mar 2025 15:12:57 +0300 Subject: [PATCH] update classes --- .../05-prototypes/01-prototype-inheritance.md | 44 +++++++++++++ .../05-prototypes/02-f-prototype.md | 28 ++++++++ .../05-prototypes/03-build-in-prototypes.md | 66 +++++++++++++++++++ .../05-prototypes/04-prototype-methods.md | 31 +++++++++ docs/javascript/05-prototypes/index.md | 0 docs/javascript/06-classes/01-class-base.md | 51 ++++++++++++++ .../06-classes/02-inheritance-classes.md | 48 ++++++++++++++ .../06-classes/03-static-option-methods.md | 46 +++++++++++++ .../04-private-protected-options-methods.md | 46 +++++++++++++ docs/javascript/06-classes/05-class-check.md | 46 +++++++++++++ docs/javascript/06-classes/06-mixins.md | 15 +++++ docs/javascript/06-classes/index.md | 0 12 files changed, 421 insertions(+) create mode 100644 docs/javascript/05-prototypes/01-prototype-inheritance.md create mode 100644 docs/javascript/05-prototypes/02-f-prototype.md create mode 100644 docs/javascript/05-prototypes/03-build-in-prototypes.md create mode 100644 docs/javascript/05-prototypes/04-prototype-methods.md delete mode 100644 docs/javascript/05-prototypes/index.md create mode 100644 docs/javascript/06-classes/01-class-base.md create mode 100644 docs/javascript/06-classes/02-inheritance-classes.md create mode 100644 docs/javascript/06-classes/03-static-option-methods.md create mode 100644 docs/javascript/06-classes/04-private-protected-options-methods.md create mode 100644 docs/javascript/06-classes/05-class-check.md create mode 100644 docs/javascript/06-classes/06-mixins.md delete mode 100644 docs/javascript/06-classes/index.md diff --git a/docs/javascript/05-prototypes/01-prototype-inheritance.md b/docs/javascript/05-prototypes/01-prototype-inheritance.md new file mode 100644 index 0000000..c552ada --- /dev/null +++ b/docs/javascript/05-prototypes/01-prototype-inheritance.md @@ -0,0 +1,44 @@ +--- +sidebar_position: 1 +--- + +# Прототипное наследование + +- В JavaScript все объекты имеют скрытое свойство `[[Prototype]]`, которое является либо другим объектом, либо `null`. +- Мы можем использовать `obj.__proto__` для доступа к нему (исторически обусловленный геттер/сеттер, есть другие способы, которые скоро будут рассмотрены). +- Объект, на который ссылается `[[Prototype]]`, называется «прототипом». +- Если мы хотим прочитать свойство `obj` или вызвать метод, которого не существует у `obj`, тогда JavaScript попытается найти его в прототипе. +- Операции записи/удаления работают непосредственно с объектом, они не используют прототип (если это обычное свойство, а не сеттер). +- Если мы вызываем `obj.method()`, а метод при этом взят из прототипа, то `this` всё равно ссылается на `obj`. Таким образом, методы всегда работают с текущим объектом, даже если они наследуются. +- Цикл `for..in` перебирает как свои, так и унаследованные свойства. Остальные методы получения ключей/значений работают только с собственными свойствами объекта. + +## Prototype +В JavaScript объекты имеют специальное скрытое свойство `[[Prototype]]` (так оно названо в спецификации), которое либо равно `null`, либо ссылается на другой объект.\ +Когда мы хотим прочитать свойство из object, а оно отсутствует, JavaScript автоматически берёт его из прототипа. В программировании такой механизм называется «прототипным наследованием». + +Свойство `[[Prototype]]` является внутренним и скрытым, но есть много способов задать его. + +Одним из них является использование `__proto__` + +💥 Свойство `__proto__` — исторически обусловленный геттер/сеттер для `[[Prototype]]`\ +Обратите внимание, что __proto__ — не то же самое, что внутреннее свойство [[Prototype]]. + +Это геттер/сеттер для `[[Prototype]]`. Позже мы увидим ситуации, когда это имеет значение, а пока давайте просто будем иметь это в виду, поскольку мы строим наше понимание языка JavaScript. + +Свойство `__proto__` немного устарело, оно существует по историческим причинам. Современный JavaScript предполагает, что мы должны использовать функции `Object.getPrototypeOf/Object.setPrototypeOf` вместо того, чтобы получать/устанавливать прототип. Мы также рассмотрим эти функции позже. + +По спецификации `__proto__` должен поддерживаться только браузерами, но по факту все среды, включая серверную, поддерживают его. Так что мы вполне безопасно его используем. + +## Операция записи не использует прототип +Прототип используется только для чтения свойств. \ +Операции записи/удаления работают напрямую с объектом. + +## Значение «this» +***Неважно, где находится метод: в объекте или его прототипе. При вызове метода `this` — всегда объект перед точкой.*** + +Таким образом, вызов сеттера `admin.fullName=` в качестве `this` использует `admin`, а не `user`. + +## Цикл for…in +Цикл `for..in` проходит не только по собственным, но и по унаследованным свойствам объекта. + +Если унаследованные свойства нам не нужны, то мы можем отфильтровать их при помощи встроенного метода `obj.hasOwnProperty(key)`: он возвращает `true`, если у `obj` есть собственное, не унаследованное, свойство с именем `key`. diff --git a/docs/javascript/05-prototypes/02-f-prototype.md b/docs/javascript/05-prototypes/02-f-prototype.md new file mode 100644 index 0000000..fb05d09 --- /dev/null +++ b/docs/javascript/05-prototypes/02-f-prototype.md @@ -0,0 +1,28 @@ +--- +sidebar_position: 2 +--- + +# F.prototype + +Как мы помним, новые объекты могут быть созданы с помощью функции-конструктора new F(). + +Если в F.prototype содержится объект, оператор new устанавливает его в качестве [[Prototype]] для нового объекта. + +💥 На заметку: +JavaScript использовал прототипное наследование с момента своего появления. Это одна из основных особенностей языка. + +Но раньше, в старые времена, прямого доступа к прототипу объекта не было. Надёжно работало только свойство "prototype" функции-конструктора, описанное в этой главе. Поэтому оно используется во многих скриптах. + +- Свойство `F.prototype` (не путать с `[[Prototype]]`) устанавливает `[[Prototype]]` для новых объектов при вызове `new F()`. +- Значение `F.prototype` должно быть либо объектом, либо `null`. Другие значения не будут работать. +- Свойство `"prototype"` является особым, только когда оно назначено функции-конструктору, которая вызывается оператором `new`. +- +В обычных объектах prototype не является чем-то особенным: +```js +let user = { + name: "John", + prototype: "Bla-bla" // никакой магии нет - обычное свойство +}; +``` + +По умолчанию все функции имеют `F.prototype = { constructor: F }`, поэтому мы можем получить конструктор объекта через свойство `"constructor"`. \ No newline at end of file diff --git a/docs/javascript/05-prototypes/03-build-in-prototypes.md b/docs/javascript/05-prototypes/03-build-in-prototypes.md new file mode 100644 index 0000000..95c79f3 --- /dev/null +++ b/docs/javascript/05-prototypes/03-build-in-prototypes.md @@ -0,0 +1,66 @@ +--- +sidebar_position: 3 +--- + +# Встроенные прототипы + +- Все встроенные объекты следуют одному шаблону: + - Методы хранятся в прототипах (Array.prototype, Object.prototype, Date.prototype и т.д.). + - Сами объекты хранят только данные (элементы массивов, свойства объектов, даты). +- Примитивы также хранят свои методы в прототипах объектов-обёрток: Number.prototype, String.prototype, Boolean.prototype. Только у значений undefined и null нет объектов-обёрток. +- Встроенные прототипы могут быть изменены или дополнены новыми методами. Но не рекомендуется менять их. Единственная допустимая причина – это добавление нового метода из стандарта, который ещё не поддерживается движком JavaScript. + + +## Object.prototype +Краткая нотация `obj = {}` – это то же самое, что и `obj = new Object()`, где `Object` – встроенная функция-конструктор для объектов с собственным свойством `prototype`, которое ссылается на огромный объект с методом `toString` и другими. +```js +let obj = {}; +alert( obj ); // "[object Object]" ? +``` +Таким образом, когда вызывается obj.toString(), метод берётся из Object.prototype. + +## Другие встроенные прототипы +Другие встроенные объекты, такие как Array, Date, Function и другие, также хранят свои методы в прототипах. + +## Примитивы +Самое сложное происходит со строками, числами и булевыми значениями. + +Если мы попытаемся получить доступ к их свойствам, то тогда будет создан временный объект-обёртка с использованием встроенных конструкторов String, Number и Boolean, который предоставит методы и после этого исчезнет. +Эти объекты создаются невидимо для нас, и большая часть движков оптимизирует этот процесс, но спецификация описывает это именно таким образом. Методы этих объектов также находятся в прототипах, доступных как String.prototype, Number.prototype и Boolean.prototype. + +💥 **Значения null и undefined не имеют объектов-обёрток** + +## Изменение встроенных прототипов +Встроенные прототипы можно изменять. Например, если добавить метод к String.prototype, метод становится доступен для всех строк: +```js +String.prototype.show = function() { + alert(this); +}; +"BOOM!".show(); // BOOM! +``` +💥 Важно: +Прототипы глобальны, поэтому очень легко могут возникнуть конфликты. Если две библиотеки добавляют метод String.prototype.show, то одна из них перепишет метод другой. + +Изменение встроенных прототипов считается плохой идеей. +*** В современном программировании есть только один случай, в котором одобряется изменение встроенных прототипов. Это создание полифилов.*** + +## Заимствование у прототипов +Некоторые методы встроенных прототипов часто одалживают. + +Например, если мы создаём объект, похожий на массив (псевдомассив), мы можем скопировать некоторые методы из Array в этот объект. +```js +let obj = { + 0: "Hello", + 1: "world!", + length: 2, +}; +obj.join = Array.prototype.join; +alert( obj.join(',') ); // Hello,world! +``` +Это работает, потому что для внутреннего алгоритма встроенного метода `join` важны только корректность индексов и свойство `length`, он не проверяет, является ли объект на самом деле массивом. И многие встроенные методы работают так же. + +Альтернативная возможность – мы можем унаследовать от массива, установив `obj.__proto__` как `Array.prototype`, таким образом все методы `Array` станут автоматически доступны в `obj`. + +Но это будет невозможно, если `obj` уже наследует от другого объекта. Помните, мы можем наследовать только от одного объекта одновременно. + +Заимствование методов – гибкий способ, позволяющий смешивать функциональность разных объектов по необходимости. \ No newline at end of file diff --git a/docs/javascript/05-prototypes/04-prototype-methods.md b/docs/javascript/05-prototypes/04-prototype-methods.md new file mode 100644 index 0000000..51c71d0 --- /dev/null +++ b/docs/javascript/05-prototypes/04-prototype-methods.md @@ -0,0 +1,31 @@ +--- +sidebar_position: 4 +--- + +# Методы прототипов, объекты без свойства __proto__ +Свойство `__proto__` считается устаревшим, и по стандарту оно должно поддерживаться только браузерами. + +Современные же методы это: + +- `Object.create(proto[, descriptors])` – создаёт пустой объект со свойством [[Prototype]], указанным как proto, и необязательными дескрипторами свойств `descriptors`. +- `Object.getPrototypeOf(obj)` – возвращает свойство `[[Prototype]]` объекта `obj`. +- `Object.setPrototypeOf(obj, proto)` – устанавливает свойство `[[Prototype]]` объекта `obj` как `proto`. + +Эти методы нужно использовать вместо `__proto__`. + +Встроенный геттер/сеттер `__proto__` не безопасен, если мы хотим использовать созданные пользователями ключи в объекте. Как минимум потому, что пользователь может ввести "__proto__" как ключ, от чего может возникнуть ошибка. Если повезёт – последствия будут лёгкими, но, вообще говоря, они непредсказуемы. + +Так что мы можем использовать либо `Object.create(null)` для создания «простейшего» объекта, либо использовать коллекцию `Map`. + +Кроме этого, `Object.create` даёт нам лёгкий способ создать поверхностную копию объекта со всеми дескрипторами: + +`__proto__` – это геттер/сеттер для свойства `[[Prototype]]`, и находится он в `Object.prototype`, как и другие методы. + +Ещё методы: +- `Object.keys(obj)` / `Object.values(obj)` / `Object.entries(obj)` – возвращают массив всех перечисляемых собственных строковых ключей/значений/пар ключ-значение. +- `Object.getOwnPropertySymbols(obj)` – возвращает массив всех собственных символьных ключей. +- `Object.getOwnPropertyNames(obj)` – возвращает массив всех собственных строковых ключей. +- `Reflect.ownKeys(obj)` – возвращает массив всех собственных ключей. +- `obj.hasOwnProperty(key)`: возвращает `true`, если у `obj` есть собственное (не унаследованное) свойство с именем `key`. + +Все методы, которые возвращают свойства объектов (такие как `Object.keys` и другие), возвращают «собственные» свойства. Если мы хотим получить и унаследованные, можно воспользоваться циклом `for..in`. \ No newline at end of file diff --git a/docs/javascript/05-prototypes/index.md b/docs/javascript/05-prototypes/index.md deleted file mode 100644 index e69de29..0000000 diff --git a/docs/javascript/06-classes/01-class-base.md b/docs/javascript/06-classes/01-class-base.md new file mode 100644 index 0000000..9ccf3cd --- /dev/null +++ b/docs/javascript/06-classes/01-class-base.md @@ -0,0 +1,51 @@ +--- +sidebar_position: 1 +--- + +# Класс: базовый синтаксис +MyClass технически является функцией (той, которую мы определяем как constructor), в то время как методы, геттеры и сеттеры записываются в MyClass.prototype. + +## Синтаксис «class» +```js +class MyClass { + // методы класса + constructor() { ... } + method1() { ... } + method2() { ... } + method3() { ... } + ... +} +``` +Затем используйте вызов `new MyClass()` для создания нового объекта со всеми перечисленными методами. + +При этом автоматически вызывается метод `constructor()`, в нём мы можем инициализировать объект. + +💥 **Методы в классе не разделяются запятой** + +## Что такое класс? +В JavaScript класс – это разновидность функции. + +Вот что на самом деле делает конструкция `class User {...}`: + +1. Создаёт функцию с именем `User`, которая становится результатом объявления класса. Код функции берётся из метода `constructor` (она будет пустой, если такого метода нет). +2. Сохраняет все методы, такие как `sayHi`, в `User.prototype`. + +При вызове метода объекта `new User` он будет взят из прототипа, как описано в главе `F.prototype`. Таким образом, объекты new User имеют доступ к методам класса. + +## Геттеры/сеттеры, другие сокращения +Как и в литеральных объектах, в классах можно объявлять вычисляемые свойства, геттеры/сеттеры и т.д. +При объявлении класса геттеры/сеттеры создаются на `User.prototype` + +## Свойства классов +В приведённом выше примере у класса `User` были только методы. +```js +class User { + name = "Аноним"; + + sayHi() { + alert(`Привет, ${this.name}!`); + } +} +new User().sayHi(); +``` +Свойство name не устанавливается в `User.prototype`. Вместо этого оно создаётся оператором `new` перед запуском конструктора, это именно свойство объекта. \ No newline at end of file diff --git a/docs/javascript/06-classes/02-inheritance-classes.md b/docs/javascript/06-classes/02-inheritance-classes.md new file mode 100644 index 0000000..231a7a8 --- /dev/null +++ b/docs/javascript/06-classes/02-inheritance-classes.md @@ -0,0 +1,48 @@ +--- +sidebar_position: 2 +--- + +# Наследование классов +Наследование классов – это способ расширения одного класса другим классом. +Таким образом, мы можем добавить новый функционал к уже существующему. + +1. Чтобы унаследовать от класса: class Child extends Parent: + -При этом Child.prototype.__proto__ будет равен Parent.prototype, так что методы будут унаследованы. +2. При переопределении конструктора: + - Обязателен вызов конструктора родителя super() в конструкторе Child до обращения к this. +3. При переопределении другого метода: + - Мы можем вызвать super.method() в методе Child для обращения к методу родителя Parent. +4. Внутренние детали: + - Методы запоминают свой объект во внутреннем свойстве [[HomeObject]]. Благодаря этому работает super, он в его прототипе ищет родительские методы. + - Поэтому копировать метод, использующий super, между разными объектами небезопасно. + +- У стрелочных функций нет своего this и super, поэтому они «прозрачно» встраиваются во внешний контекст. + +## Ключевое слово «extends» +Синтаксис создания класса допускает указывать после extends не только класс, но и любое выражение. +Пример вызова функции, которая генерирует родительский класс: +```js +function f(phrase) { + return class { + sayHi() { alert(phrase); } + }; +} +class User extends f("Привет") {} +new User().sayHi(); // Привет +``` +Здесь class User наследует от результата вызова f("Привет"). + +## Переопределение методов +```js +class Rabbit extends Animal { + stop() { + // ...теперь это будет использоваться для rabbit.stop() + // вместо stop() из класса Animal + } +} +``` + +У классов есть ключевое слово "super", чтобы сделать новый на его основе, изменяя или расширяя его функциональность + +super.method(...) вызывает родительский метод. +super(...) для вызова родительского конструктора (работает только внутри нашего конструктора). \ No newline at end of file diff --git a/docs/javascript/06-classes/03-static-option-methods.md b/docs/javascript/06-classes/03-static-option-methods.md new file mode 100644 index 0000000..8d26c83 --- /dev/null +++ b/docs/javascript/06-classes/03-static-option-methods.md @@ -0,0 +1,46 @@ +--- +sidebar_position: 3 +--- + +# Статические свойства и методы +Статические методы используются для функциональности, принадлежат классу «в целом», а не относятся к конкретному объекту класса. + +Например, метод для сравнения двух статей Article.compare(article1, article2) или фабричный метод Article.createTodays(). + +В объявлении класса они помечаются ключевым словом static. + +Статические свойства используются в тех случаях, когда мы хотели бы сохранить данные на уровне класса, а не какого-то одного объекта. + +```js +class MyClass { + static property = ...; + + static method() { + ... + } +} +``` +Технически, статическое объявление – это то же самое, что и присвоение классу: +``` +MyClass.property = ... +MyClass.method = ... +``` +Статические свойства и методы наследуются. + +Для class B extends A прототип класса B указывает на A: B.[[Prototype]] = A. Таким образом, если поле не найдено в B, поиск продолжается в A. + +## Статические свойства +Статические свойства также возможны, они выглядят как свойства класса, но с static в начале: +```js +class Article { + static publisher = "Илья Кантор"; +} +alert( Article.publisher ); // Илья Кантор +``` +Это то же самое, что и прямое присваивание Article: +``` +Article.publisher = "Илья Кантор"; +``` + +## Наследование статических свойств и методов +Статические свойства и методы наследуются. \ No newline at end of file diff --git a/docs/javascript/06-classes/04-private-protected-options-methods.md b/docs/javascript/06-classes/04-private-protected-options-methods.md new file mode 100644 index 0000000..6a88808 --- /dev/null +++ b/docs/javascript/06-classes/04-private-protected-options-methods.md @@ -0,0 +1,46 @@ +--- +sidebar_position: 4 +--- + +# Приватные и защищённые методы и свойства +В терминах ООП отделение внутреннего интерфейса от внешнего называется инкапсуляция. + +Это даёт следующие выгоды: + +**Защита для пользователей, чтобы они не выстрелили себе в ногу** + +Если мы чётко отделим внутренний интерфейс, то разработчик класса сможет свободно менять его внутренние свойства и методы, даже не информируя пользователей… +#### Поддерживаемость +Если вы разработчик такого класса, то приятно знать, что приватные методы можно безопасно переименовывать, их параметры можно изменять и даже удалять, потому что от них не зависит никакой внешний код. + +В новой версии вы можете полностью всё переписать, но пользователю будет легко обновиться, если внешний интерфейс остался такой же. + +## Внутренний и внешний интерфейсы +В объектно-ориентированном программировании свойства и методы разделены на 2 группы: + +- Внутренний интерфейс – методы и свойства, доступные из других методов класса, но не снаружи класса. +- Внешний интерфейс – методы и свойства, доступные снаружи класса. + +Итак, всё, что нам нужно для использования объекта, это знать его внешний интерфейс. Мы можем совершенно не знать, как это работает внутри, и это здорово. + +В JavaScript есть два типа полей (свойств и методов) объекта: +- Публичные: доступны отовсюду. Они составляют внешний интерфейс. До этого момента мы использовали только публичные свойства и методы. +- Приватные: доступны только внутри класса. Они для внутреннего интерфейса. + +Защищённые поля не реализованы в JavaScript на уровне языка, но на практике они очень удобны, поэтому их эмулируют. + +## Защищённое свойство «waterAmount» +Защищённые свойства обычно начинаются с префикса `_`. + +Это не синтаксис языка: есть хорошо известное соглашение между программистами, что такие свойства и методы не должны быть доступны извне. Большинство программистов следуют этому соглашению. + +## Приватное свойство «#waterLimit» +Есть новшество в языке JavaScript, которое почти добавлено в стандарт: оно добавляет поддержку приватных свойств и методов. + +Приватные свойства и методы должны начинаться с #. Они доступны только внутри класса. + +Например, в классе ниже есть приватное свойство #waterLimit и приватный метод #checkWater для проверки количества воды + +На уровне языка # является специальным символом, который означает, что поле приватное. Мы не можем получить к нему доступ извне или из наследуемых классов. + +Приватные поля не конфликтуют с публичными. У нас может быть два поля одновременно – приватное #waterAmount и публичное waterAmount. \ No newline at end of file diff --git a/docs/javascript/06-classes/05-class-check.md b/docs/javascript/06-classes/05-class-check.md new file mode 100644 index 0000000..ab9b155 --- /dev/null +++ b/docs/javascript/06-classes/05-class-check.md @@ -0,0 +1,46 @@ +--- +sidebar_position: 5 +--- + +# Проверка класса: "instanceof" + +| | работает для | возвращает | +|-------------|----------------------------------------------------------------|------------| +| typeof | примитивов | строка | +| {}.toString | примитивов, встроенных объектов, объектов с Symbol.toStringTag | строка | +| instanceof | объектов | true/false | + +Как мы можем видеть, технически `{}.toString` «более продвинут», чем `typeof`. + +А оператор `instanceof` – отличный выбор, когда мы работаем с иерархией классов и хотим делать проверки с учётом наследования. + +## Оператор instanceof +```js +obj instanceof Class +``` +Оператор вернёт `true`, если `obj` принадлежит классу Class или наследующему от него. + +## Object.prototype.toString возвращает тип +У `toString` имеются скрытые возможности, которые делают метод гораздо более мощным. Мы можем использовать его как расширенную версию `typeof` и как альтернативу `instanceof`. + +Согласно спецификации встроенный метод `toString` может быть позаимствован у объекта и вызван в контексте любого другого значения. И результат зависит от типа этого значения. + +- Для числа это будет [object Number] +- Для булева типа это будет [object Boolean] +- Для null: [object Null] +- Для undefined: [object Undefined] +- Для массивов: [object Array] +- …и т.д. (поведение настраивается). + +## Symbol.toStringTag +Поведение метода объектов `toString` можно настраивать, используя специальное свойство объекта `Symbol.toStringTag`. +```js +// toStringTag для браузерного объекта и класса +alert( window[Symbol.toStringTag]); // window +alert( XMLHttpRequest.prototype[Symbol.toStringTag] ); // XMLHttpRequest +alert( {}.toString.call(window) ); // [object Window] +alert( {}.toString.call(new XMLHttpRequest()) ); // [object XMLHttpRequest] +``` +В итоге мы получили «typeof на стероидах», который не только работает с примитивными типами данных, но также и со встроенными объектами, и даже может быть настроен. + +Можно использовать `{}.toString.call` вместо `instanceof` для встроенных объектов, когда мы хотим получить тип в виде строки, а не просто сделать проверку. \ No newline at end of file diff --git a/docs/javascript/06-classes/06-mixins.md b/docs/javascript/06-classes/06-mixins.md new file mode 100644 index 0000000..cc6ee69 --- /dev/null +++ b/docs/javascript/06-classes/06-mixins.md @@ -0,0 +1,15 @@ +--- +sidebar_position: 6 +--- + +# Примеси +По определению из Википедии, примесь – это класс, методы которого предназначены для использования в других классах, причём без наследования от примеси. + +Примесь – общий термин в объектно-ориентированном программировании: класс, который содержит в себе методы для других классов. + +С примесями могут возникнуть конфликты, если они перезаписывают существующие методы класса. Стоит помнить об этом и быть внимательнее при выборе имён для методов примеси, чтобы их избежать. + +## Пример примеси +Простейший способ реализовать примесь в JavaScript – это создать объект с полезными методами, которые затем могут быть легко добавлены в прототип любого класса.\ +Это не наследование, а просто копирование методов. +Примеси могут наследовать друг друга. diff --git a/docs/javascript/06-classes/index.md b/docs/javascript/06-classes/index.md deleted file mode 100644 index e69de29..0000000