Как и у объектов в реальной жизни, у объектов в JavaScript есть свойства и то, что они могут делать. Я создал объект массива, и он имеет свойство длины двух элементов внутри и имеет доступ к методам, как показано в раскрывающемся списке [[Prototype]] (или __proto__ в некоторых браузерах).

Другой способ создания массива — использование конструктора массива с использованием ключевого слова new и функции конструктораArray, например: . Здесь мы также получаем массив, как видно из прототипа.

Мы можем создавать не только массивы, но и другие типы объектов с помощью конструкторов. Давайте теперь создадим пустой объект, используя тот же метод.

Теперь поговорим о примитивных значениях. Как использовать методы для примитивных значений, таких как строки (string, number, boolean, null, undefined НЕ являются объектами в JavaScript) даже если они у вас нет доступа к каким-либо методам, подобным нашим предыдущим примерам? Мы можем это сделать, потому что под капотом JavaScript заключает их в оболочку объекта, как только мы используем для них метод, возвращает значение, а затем разворачивает их обратно в исходное состояние. Вскоре после этого мы увидим демонстрацию.

Теперь мы на самом деле увидим демонстрацию того, как именно JavaScript оборачивает примитивные значения, такие как строки, внутри оболочки объекта. Для этого мы снова используем функцию конструктора Stringс ключевым словом new и видим, что строка перенесена внутри объекта и имеет методы, доступные для использования в [[Prototype]]. Это именно то, что происходит автоматически под капотом, когда мы создаем строку обычным способом, без использования функции конструктора.

Единственными примитивными значениями, которые не заключены в оболочку объекта, являются null и undefined. Следовательно, у них никогда не будет доступа к каким-либо методам, подобным примерам, которые мы видели до сих пор.

Давайте еще раз рассмотрим литералы объектов, прежде чем углубляться в тему.

Ниже я создал два пользовательских объекта, userOne и userTwo, которые имеют схожие свойства и функции. Используя объектный литерал, мы должны повторить себя дважды, чтобы создать два похожих объекта. Только представьте, сколько повторений потребуется, если мы создадим 10, 20 или более таких пользователей. Это очень неэффективно и отнимает много времени. И здесь в игру вступает объектно-ориентированное программирование.

В следующем примере я создал два пользовательских объекта, используя ключевое слово new и конструктор класса. Важно помнить, что когда ключевое слово new используется с конструктором класса, оно создает объект и принимает свойства и функции, которые мы передаем внутри конструктора класса. В этом примере мы создаем свойства и функции (или методы) для двух разных пользовательских объектов, которые мы создаем с помощью new User();

Поэтому, если мы создадим еще больше пользователей с помощью new User(), каждый из них унаследует все свойства и функции, которые мы создали в нашем конструкторе класса выше.

Из приведенного выше примера видно, что нам нужно записать наши методы login() и logout() на пользователей по отдельности без возможности объединения их в цепочку. Это потому, что мы не возвращаем явно значение внутри наших методов. JavaScript по умолчанию присваивает таким функциям или методам значение undefined. Невозможно использовать метод для неопределенного метода в JavaScript. Итак, давайте посмотрим, как мы можем обойти эту проблему и связать два или более метода в пользовательском объекте.

В приведенном выше примере я создал дополнительное свойство score и функцию incScore(), которая увеличивает оценку каждого пользователя на 1 при каждом ее вызове. Кроме того, я установил явное значение return для каждой функции. В каждом операторе return this ссылается на сам объект. Поскольку мы явно устанавливаем возвращаемое значение экземпляра объекта для функций внутри конструктора класса, мы можем связать методы вместе для каждого пользователя. Опять же, если мы вернем другое значение вместо возврата this, методы больше нельзя будет связать в цепочку.

До сих пор мы видели, как мы можем создавать нескольких пользователей, используя последнюю версию объектно-ориентированного программирования ES6, не повторяясь. Но что, если мы хотим создать особый тип пользователя, например администратора, у которого может быть возможность удалять других пользователей в дополнение ко всем свойствам и методам обычных пользователей, которых мы создали?

Итак, в нашем следующем примере мы увидим, как мы можем создать пользователя-администратора, который не только будет иметь все свойства и методы обычных пользователей, но и дополнительные методы для удаления других пользователей. Обычные пользователи не будут иметь доступа к этому методу удаления. И мы добьемся этого, не переписывая свойства и методы, которые мы уже создали для обычных пользователей. Здесь в игру вступает наследование классов. Администратор унаследует свойства и методы обычных пользователей, имея при этом доступ к отдельному методу, например, возможность удалять других пользователей.

Для этого мы создаем новый класс конструктора для администратора под классом пользователя с ключевыми словами extends и super. Вместе эти два ключевых слова наследуют все свойства и функции класса User. А внутри класса Admin мы дали ему отдельное свойство title и создали функцию deleteUser(), доступную только этому администратору. Также обратите внимание, что мы создали новый Admin() после пользователей и передали его собственные значения.

Теперь давайте посмотрим на результат в консоли.

Мы видим, что здесь происходит довольно много вещей.

Во-первых, когда мы выходим из массива пользователей после вызова deleteUser(userTwo), мы видим, что userTwo, robin, больше не находится в массиве users .

Во-вторых, что более важно, при раскрытии объекта Admin мы видим, что он унаследовал свойства username, email и score. от других Пользователей и имеет собственное свойство 'title', которого нет у Пользователей выше.

Мы также видим в его [[Prototype]], что он имеет конструктор класса Admin и имеет доступ к собственному методу deleteUser(). Два указанных выше объекта User НЕ имеют доступа к этому методу deleteUser().

Внутри этого [[Prototype]] вложен еще один [[Prototype]], содержащий методы, в точности аналогичные объектам User выше. Это означает, что администратор унаследовал эти методы от объектов пользователя, созданных до него, что мы уже обсуждали ранее. Но тот факт, что эти методы от других пользователей также доступны внутри его [[Prototype]], называется Prototypal Inheritance. Это интересная тема, которую я оставлю для нашего следующего обсуждения.

А пока удачного кодирования!