Наследство — не то, что оставит тебе папа, а это

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

Предположим, у нас есть два чистых объекта, имеющих простую функцию talk.

const me = {
    talk() {
        return 'talking'
    }
}

consts you = {
    talk() {
        return 'talking'
    }
}

Итак, мы с тобой оба люди, и мы оба можем говорить. Здесь у нас есть 2 основные проблемы. Во-первых, проблема заключается в том, что мы называем дублированием кода, то есть нам пришлось написать функцию talk() дважды, один раз для вас и один для меня :D

Я имею в виду, в чем проблема с этим? это всего лишь одна строка кода, которую я напишу дважды. Как программист, важно признать, что повторение кода должно быть сведено к минимуму, учитывая сложность реальных функций, где краткие однострочники не являются нормой. Логика обычно сложнее. Итак, вместо 2 строк предположим, что у нас есть 100 строк кода, а у вас получится 200 строк. Но даже тогда разумно сказать, ну и что?? , я просто скопирую строки и вставлю их. Например, допустим, у нас есть объект «я», объект «ты», объект «она» и объект «он» или объект «они/они». Нам пришлось бы копировать функциональность для каждого отдельного объекта, что привело бы к большому дублированию кода. В реальных проектах это большое нет.

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

Итак, чтобы исправить это, у нас есть концепция наследования. Начнем с наследования на основе классов.

class Person {
    talk() {
        return 'talking';
    }
}

а затем я могу создать несколько объектов, используя шаблон класса Person.

const me = new Person();
const you = new Person();
const lgtv = new Person();

me.talk();
you.talk();
lgtv.talk();

Это решает изначальную проблему дублирования кода. Теперь вопрос обновления функции, так как мы можем это исправить? Были ли какие-либо проблемы с функцией? я должен сделать, как me.talk = someotherfunction() вы можете спросить?

мы можем это сделать, но мы действительно не должны. Давайте посмотрим, почему.

давайте посмотрим на объект меня, утешив его.

console.log(me);

который имеет тип Person, на нем нет функции разговора, вы можете видеть, что на нем есть что-то под названием Prototype. Если мы откроем прототип, то увидим на нем кое-что интересное.

У нас есть конструктор, и наша собственная функция разговора, и некоторые другие вещи, но дело в том, что у меня непосредственно нет функции разговора. и если мы сделаем один шаг и скажем me.age=12 ну тогда,

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

Имейте это в виду, пока давайте посмотрим на наш класс Person. Это действительно не очень сильно проявляется.

Но если мы утешим Person.prototype, мы увидим некоторые знакомые вещи, которые мы видели на мне.

и вы можете спросить сейчас, они похожи? давайте посмотрим на это.

так что они одно и то же. значение,

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

и если мы вызовем нашу функцию me.talk(), мы получим

Вот это хороший разговор :3

и это в некотором смысле то, как наследование на основе классов работает в JS, по сути, это просто создание шаблона, от которого вы можете наследовать.

Теперь давайте на секунду отложим в сторону классы и поговорим о чистых объектах и ​​прототипах, которые дадут вам немного больше понимания о прототипах :3

Теперь другой способ наследования или основной способ наследования в Js — это то, что вы, возможно, слышали, через чистые объекты или то, что мы называем прототипным наследованием. На самом деле, в предыдущем примере, который мы взяли, используются объекты и функции, а также прототипы внизу, даже несмотря на то, что мы используем ключевое слово class, и это то, что мы называем синтаксическим сахаром, что означает, что на самом деле это не классы. Это просто удобный способ чтения и написания шаблона, потому что синтаксис объектов и Prototypal Inheritance в Js немного раздражает и странен.

Говоря о прототипном наследовании, давайте посмотрим, как оно работает внутри.

когда мы пишем class Person () {}, то, что делает Js ниже, это то, что он создает функцию с именем Person, напрямую переходит к ее прототипу и добавляет эту функцию Talk для вас.

и если мы сделаем const me=new Person();

это дает нам тот же результат, и если мы посмотрим на меня

это точно такая же идея. Мы говорим не об объекте, а о его прототипе.

Другой способ добиться этого — сказать:

и me.talk все еще работает. Впрочем, здесь есть разница, если утешить меня возражением.

разговор идет прямо о предмете, но что это значит? и почему это вообще важно?

Что ж, то, что мы только что создали, является объектом-конструктором, и все, что мы добавим к этому объекту, не будет рассматриваться как метод, оно будет рассматриваться как свойство, такое же, как строка, логическое значение или число. Таким образом, функция, для которой вы написали логику, фактически копируется в этот экземпляр или дочерний объект. В то время как если вы добавите его в качестве прототипа, он будет считаться методом. Так что плохого в том, чтобы иметь это как собственность? Технически доступ к нему осуществляется так же, как мы видели. Но, как я уже сказал, он копируется во все экземпляры или дочерние объекты.

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

Точно так же обновление свойства объекта не будет каскадным во всех других экземплярах этого объекта.

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

давайте определим функцию-конструктор со свойством age равным 12. Затем определим объект me как Person, и мы увидим, что у объекта me уже есть свойство age равное 12. Теперь, если мы скажем, Person.age=40, и если мы утешим и человека, и меня.

мне объект все еще имеет возраст 12. Итак, что здесь произошло? Я думал, что просто поменял.

Ну, а если присмотреться,

Человек фактически не имеет возраста ни на себе, ни на своем прототипе. Это просто свойство объекта, который является экземпляром этой функции Person. , Он принадлежит только мне и получает добавленный ко мне объект.

Итак, это очень удобный способ добавить все свойства к объекту this внутри конструктора и все методы к его прототипам.

Это также дает нам четкое представление о моих вещах, возрасте, имени, поле и т. д., а также обо всех методах/поведении, которые у меня есть.

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

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

скажем

class Person {
    talk() {
        return 'talking';
    }
}
const me = new Person();

и теперь у нас есть, скажем, еще один класс, расширяющий Person.

class SuperPerson extends Person {
    fly() {
        return 'I can Fly!!!';
    }
}

а теперь, мой друг, ты Суперчеловек.

const you=new SuperPerson();

Итак, давайте посмотрим, работает не только you.fly(), но и you.talk() :D, что довольно интересно, потому что у SuperPerson нет функции разговора, но он расширяет класс Person, у которого есть функция разговора. Однако me.fly() не сработает, потому что я всего лишь человек.

Наконец, у нас есть чистое наследование объектов.

const Person = {
    talk() {
        return 'talking';
    }
}

Итак, как я могу создать объект «я», который является экземпляром этого человека, и использовать функцию разговора?

для этого, мы можем сказать,

const me = Object.create(Person);

другой способ, которым мы можем добиться того же, говоря.

const me = {} //Just a pure object.

Object.setPrototypeOf(me, Person);// where the first parameter is instance
                                 // and second parameter is just the parent
                                // where you want to inherit from

Вывод:3

Почему наследование, Где наследование?

Итак, где мы используем наследование? хорошо, если у вас есть объекты с общим или похожим поведением, или компоненты с похожей функциональностью, возможно, в обработчиках событий, clickHandlers, где каждый раз, когда вы делаете это, вы создаете шаблон, который можно повторно использовать снова и снова, просто создав класс шаблона и вызывать нужные методы, а класс позаботится об этом за вас.

Несмотря на то, что о наследовании можно рассказать еще много, надеюсь, вы уловили суть.