Привет, ребята, за последние пару месяцев я взял интервью у нескольких парней. Большинство из них знакомы с такими понятиями, как замыкания, промисы и т. д., но когда я спрашиваю их о наследовании, они всегда упоминают ключевое слово extends, но лишь немногие упоминают (или, по крайней мере, знают) цепочку prototype.

Расширяет новый прототип

Совершенно неправильно! extends — это просто синтаксический сахар для prototype за кулисами JS указывает родительскому классу на constructor prototype .

Чтобы понять это, давайте возьмем следующий вопрос интервью (один из моих любимых, должен сказать):

Используя наследование, передайте функцию multiply новому Array . Эта функция должна изменять текущий массив, добавляя те же значения, но умножая их на себя:

const a = [1,2, 3,4,5]
a.multiply()
console.log(1) // [1,2,3,4,5,1,4,9,16,25]

Для опытных разработчиков ответ действительно прост, нам просто нужно использовать цепочку prototype. Но для сумасшедших/гениальных разработчиков prototype — не единственный ответ, поскольку мы можем создавать массивы с помощью ключевого слова new, тогда мы также можем использовать extends!

Как видите, помимо другого синтаксиса, есть одно большое отличие: при использовании prototype все массивы, даже созданные с использованием ключевого слова new, имеют доступ к функции multiply. Но почему? хорошо давайте посмотрим на объект

Arrayявляется итерируемым объектом по определению, и по определению все объекты имеют prototype

Прототип против наследования классов

Если мы используем Prototype Inheritance, наша функция multiply присоединяется непосредственно к Array prototype, поэтому по определению все экземпляры или вызовы будут иметь к ней доступ благодаря цепочке prototype. Вот почему переменные b и c имеют доступ к этой функции. Таким образом, мы могли бы сказать, что функция конструктора указывает itsprototype на свой родительский объект (конечно, мы можем изменить это, но по умолчанию constructor.prototype указывает на свой родительский объект).

Теперь, если мы используем наследование классов, мы видим, что отношения сильнее, почему? ну, constructor prototype, а также прямое prototype из FancyArray имеет функцию multiply, и оба указывают на объект Array, это то, что называют таксономиями классов (простыми словами: классификация классов). Итак, FancyArray — это класс типа Array.

Несмотря на то, что FancyArray таксономия Array, это не означает, что Array имеет доступ к функции multiply:

FancyArray напрямую зависит от Array, но Array не знает о кастомных модификациях, которые есть у FancyArray, так что давайте вспомним немного теории:

Наследование классов берет план в качестве основы для создания нового. Дочерний план будет иметь то же поведение, функции и ошибки, что и родительский, но родительский план ничего не будет знать о своих дочерних элементах.

Вывод

В JS нет типичного наследования классов, JS создает прочную связь между родителем и дочерним элементом, указывая свои prototype и constructor.prototype на родителя prototype . Это работает, но мы теряем прямой контроль над ребенком. По моему личному мнению, наследование классов отлично работает для таких сценариев, как React, где мы создаем Components с точно таким же поведением, как у React, конечно, мы можем добавить некоторые настройки, но эта настройка не должна распространяться на другие Components

Прототипное наследование — это косвенная связь между объектами, поскольку мы используем prototype для передачи пользовательских переменных/функций. Почему непрямой? ну, prototype представляет родительский объект, это просто ссылка от дочернего к родительскому, это означает, что он не является частью самого объекта. Чтобы доказать эту мысль, мы можем использовать функцию hasOwnProperty. Как вы, возможно, знаете, эта функция будет проверять только прямые атрибуты объекта, поэтому она игнорирует все в prototype, так как это просто представление родителя.

Время шуток…

Спасибо, что прочитали этот пост, и в качестве награды у нас есть мультфильм Дилберта!