JavaScript ES6 классы: Наследование | ReactJS

JavaScript ES6 классы: Наследование | ReactJS

С помощью наследования вы, буквально, говорите: “У меня есть один конструктор/класс и другой конструктор/класс, который точно такой же, как и первый,кромевот этого и вот этого”. Чаще всего наследование в JavaScript реализуется с помощью функцииObject.create(), позволяющий создать новый объект с заданным прототипом.

Онлайн курс по React JS в Киеве | Frontend, обучение, уроки, ментор - ReactWarriors

// функция конструктор
var Person = function(name) {
  this.name = name + ' Doe';
};

// запись метода в прототип
Person.prototype.sayName = function() {
  console.log(this.name);
};

// Вызов конструктора родителя внутри дочернего 
// конструктора для записи всех свойств
var GreatPerson = function(name, phrase) {
  Person.apply(this, arguments);
  this.phrase = phrase;
};

// Перезапить прототипа дочернего конструктора
GreatPerson.prototype = Object.create(Person.prototype);

GreatPerson.prototype.sayPhrase = function() {
  console.log(this.name + ' says: "' + this.phrase + '"');
};

// создание нового объекта
var john = new Person('John');
var jane = new GreatPerson('Jane', 'Hello, World!');

john.sayName(); // John Doe
jane.sayName(); // Jane Doe
jane.sayPhrase(); // Jane Doe says: "Hello, World!"

И здесь с JavaScript “всё не так”. Тот же самый пример, написанный на PHP:

<?php
class Person {
  public $name;
  
  public function __construct($name) {
    $this->name = $name;
  }

  public function say_name() {
    echo $this->name;
  }
}

class GreatPerson extends Person {
  public $name;
  
  public function __construct($name, $phrase) {
    parent::__construct($name);
    $this->phrase = $phrase;
   }
   
   public function say_phrase() {
    echo $this->name . " says " . $this->phrase;
  }
}

$john = new Person('john');
$john->say_name(); // john

$jane = new GreatPerson('jane', 'Hello World!');
$jane->say_phrase(); // jane says Hello World!

Да в чём вообще кроется разница? Мы же выполнили одни и те же действия, просто с разным синтаксисом! Чтобы понять, почему JavaScript другой представьте себе семейство птичек: дедушка попугай, отец попугай и сын попугай — все попугаи! Совершенно очевидно, что если у деда попугая вырастет ещё одна лапка, то это ни коем образом не повлияет на отца и сына. То есть попугай, родившийся с двумя лапами, так и останется до конца своей жизни с двумя лапами, в независимости от того, что случилось с любым из его предков. Подобным образом можно представить себе классическое наследование.

С прототипным наследование ситуация абсолютно противоположная. Дед-попугай отрастил себе третью лапку, и она автоматически появилась у отца и сына (прототипное наследование против природы). Сложившееся положение вещей крайне не понравилось отцу попугаю, и он решил, что и попугаем-то больше быть не хочет и стал орлом (с тремя лапами). Как вы уже, наверное, догадались сын попугай уже больше не попугай, а настоящий орёл (но опять же с тремя лапами). Три лапы слишком много для сына и он решает отказаться от одной (теперь у нас естьобычный орёл с двумя лапами).

Но и это ещё не всё! Единственный оставшийся попугай (дедушка) решил, что трёх лап мало и приобрёл себе ещё одну, а также решил стать ласточкой. В результаты из обычного семейства попугаев мы получили: деда ласточку с четырьмя лапами, отца орла с тремя лапами, сына орла с двумя лапами. Вот она вся сутьпрототипного наследования. Похоже на безумие? Да? Тогда перейдём к коду:

// Дед попугай с двумя лапами
var ParrotGrandfather = function() {};
ParrotGrandfather.prototype = {
  species: 'Parrot',
  paws: 2
};

// Отец попугай унаследовал всё у деда
var ParrotFather = function() {};
ParrotFather.prototype = Object.create(ParrotGrandfather.prototype);

// Сын попугай унаследовал всё у отца
var ParrotSon = function() {};
ParrotSon.prototype = Object.create(ParrotFather.prototype);

var grandfather = new ParrotGrandfather();
var father = new ParrotFather()
var son = new ParrotSon();

console.log(grandfather.species, father.species, son.species);
// Parrot Parrot Parrot - все попугаи!
console.log(grandfather.paws, father.paws, son.paws);
// 2 2 2 - у каждого по 2 лапы

// Дед меняет количество лап
ParrotGrandfather.prototype.paws++;
console.log(grandfather.paws, father.paws, son.paws);
// 3 3 3 - у каждого теперь по 3 лапы

// Отец меняет вид
ParrotFather.prototype.species = 'eagle';
console.log(grandfather.species, father.species, son.species);
// Parrot eagle eagle - дед остался попугаем, отец и сын стали орлами

// Сын уменьшил количество лап
ParrotSon.prototype.paws--;
console.log(grandfather.paws, father.paws, son.paws);
// 3 3 2 - дед и отец остались при своих трёх лапах

// Дед решил стать чайкой
ParrotGrandfather.prototype.species = 'seagull';
console.log(grandfather.species, father.species, son.species);
// seagull eagle eagle - дед чайка, отец и сын орлы

Вывод из всего выше перечисленного: в JavaScript прототипное наследование “динамическое”, можно изменять всё налету, классическое же наследование подобным похвастаться не может: всё, что вы объявили в одном классе останется там навсегда. Грубо говоря, классическое представление наследования предполагает наличие определённой статической схемы, по которой будет строиться каждый объект данного класса. В прототипном наследовании мы имеем дело не со схемой, а с живым, постоянно развивающимся организмом, который со временем изменяется и принимает ту форму, которая нам нужна (и это прекрасно). Источник

Онлайн курс по React JS в Львове | Frontend, обучение, уроки, ментор - ReactWarriors

Поделись знаниями: