С помощью наследования вы, буквально, говорите: “У меня есть один конструктор/класс и другой конструктор/класс, который точно такой же, как и первый,кромевот этого и вот этого”. Чаще всего наследование в 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